Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android databinding: how to avoid onCheckedChanged triggered by programmatically

I am now trying to use android data-binding in my project, and encounter this kind of issue, for example: I have 3 checkbox as a checkbox group, if first checkbox is checked, then a variable type is 1. the second makes type to 2, the 3rd makes type to 3. so I implement the code in this way.

   // layout.xml


   <android.support.v7.widget.AppCompatCheckBox
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:checked="@{userInfoViewModel.type == 1}"
        android:onCheckedChanged="@{(compoundButton, checked) -> userInfoViewModel.onTypeChecked(checked, 1)}"
        />

   <android.support.v7.widget.AppCompatCheckBox
        android:layout_width="50dp"
        android:layout_height="55dp"
        android:checked="@{userInfoViewModel.type == 2}"
        android:onCheckedChanged="@{(compoundButton, checked) -> userInfoViewModel.onTypeChecked(checked, 2)}"
        />

    <android.support.v7.widget.AppCompatCheckBox
        android:layout_width="50dp"
        android:layout_height="55dp"
        android:checked="@{userInfoViewModel.type == 3}"
        android:onCheckedChanged="@{(compoundButton, checked) -> userInfoViewModel.onTypeChecked(checked, 3)}"
        />

// viewModel

public void onTypeChecked(boolean checked, int i) {
    if (checked) {
        // if it is a check. set the type
        type.set(i);
    } else {
        // if it is a uncheck. set type to unknown
        type.set(0);
    }
}

Now the problem is that, if I have checked 1st checkbox, then I check the 2nd. type should be set to 2, and the UI should update correctly. But the reality is that uncheck event also occur on the 1st checkbox, after type is set to 2, then type.set(0) is triggered, so no checkbox is checked.

In fact, this issue is same to onCheckedChanged called automatically. What I need is a solution for data-binding.

In non-data-binding project, I think the best solution is using setCheckedSilent(answer by @Emanuel Andrada).

  public void setCheckedSilent(boolean checked) {
    super.setOnCheckedChangeListener(null);
    super.setChecked(checked);
    super.setOnCheckedChangeListener(listener);
}

But in data-binding, I can not do this. So is there any expert can help me out?

According to @Arpan Sharma's answer, listen to onClick instead of onCheckedChanged. This solution works currently, But I am worried about the value of checked, is it always right?

public void onTypeChecked(View view, int i) {
    Boolean checked = ((CheckBox) view).isChecked();

    if (checked) {
        type.set(i);
    } else {
        type.set(0);
    }
}
like image 381
Leon Avatar asked Mar 08 '17 08:03

Leon


People also ask

Is Android DataBinding deprecated?

Recently Android has announced that with Kotlin 1.4. 20, their Android Kotlin Extensions Gradle plugin will be deprecated and will no longer be shipped in the future Kotlin releases. Android Kotlin Extensions plugin brought with it two very cool features : Synthetics let you replace calls to findViewById with kotlinx.

Can I use ViewBinding with DataBinding?

View binding and data binding both generate binding classes that you can use to reference views directly. However, view binding is intended to handle simpler use cases and provides the following benefits over data binding: Faster compilation: View binding requires no annotation processing, so compile times are faster.

Which is better ViewBinding and DataBinding?

In short you can use ViewBinding to replace findviewbyid() effectively. If your project is however more complex and you need to add features like binding data to views, binding adapters e.t.c, use DataBinding.

What is 2 way binding in Android?

Two-way Data Binding is a technique of binding your objects to your XML layouts so that the layout can send data to your binding object. This is compared to a “traditional” or “one-way” Data Binding setup, where data would only move from your binding object to the layout.


1 Answers

Expose an ObservableBoolean from the ViewModel, then use two-way databinding over that boolean.

Then you can use the ObservableBoolean's values to decide what you want to do, rather than encode it in the XML.

android:checked="@={vm.checkedValue}"
like image 110
EpicPandaForce Avatar answered Nov 13 '22 06:11

EpicPandaForce