android数据绑定:如何避免以编程方式触发的onCheckedChanged

Leo*_*eon 12 data-binding checkbox android android-databinding

我现在正试图在我的项目中使用android数据绑定,遇到这种问题,例如:我有3个复选框作为复选框组,如果选中第一个复选框,则变量type为1.第二个使得type为2 ,第三个使得type3.所以我以这种方式实现代码.

   // 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)}"
        />
Run Code Online (Sandbox Code Playgroud)
// 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在的问题是,如果我检查了第一个复选框,那么我检查第二个.type应该设置为2,UI应该正确更新.但实际情况是,uncheck事件也发生在第一个复选框上,之后type设置为2,然后type.set(0)被触发,因此不会选中复选框.

实际上,这个问题与自动调用的onCheckedChanged相同.我需要的是数据绑定的解决方案.

在非数据绑定项目中,我认为最好的解决方案是使用setCheckedSilent(由@Emanuel Andrada回答).

  public void setCheckedSilent(boolean checked) {
    super.setOnCheckedChangeListener(null);
    super.setChecked(checked);
    super.setOnCheckedChangeListener(listener);
}
Run Code Online (Sandbox Code Playgroud)

但在数据绑定方面,我无法做到这一点.那么有专家可以帮助我吗?

根据@Arpan Sharma的回答,请听onClick而不是onCheckedChanged.这个解决方案目前有效,但我担心checked它的价值,是不是总是对的?

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

    if (checked) {
        type.set(i);
    } else {
        type.set(0);
    }
}
Run Code Online (Sandbox Code Playgroud)

Epi*_*rce 9

从 ViewModel 公开一个 ObservableBoolean,然后对该布尔值使用双向数据绑定。

然后您可以使用 ObservableBoolean 的值来决定您想要做什么,而不是在 XML 中对其进行编码。

android:checked="@={vm.checkedValue}"
Run Code Online (Sandbox Code Playgroud)


Deb*_*jan 7

我第一次遇到这个问题,我认为使用绑定适配器来实现更好。

这是绑定适配器的代码

interface OnUserCheckedChangeListener {
    fun onUserCheckChange(view:CompoundButton, isChecked:Boolean)
}
@BindingAdapter("onUserCheckedChange")
fun setUserCheckedChangeListener(view:CompoundButton, listener: OnUserCheckedChangeListener?){
    if(listener == null){
        view.setOnClickListener(null)
    }else{
        view.setOnClickListener {
            listener.onUserCheckChange(view, view.isChecked)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我们可以在任何复合按钮上使用它

<CheckBox
            android:id="@+id/finish_check"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"   
            android:checked="@{your_condition}"
            onUserCheckedChange="@{(view, checked) -> vm.onItemChecked(todo, checked)}"
            />
Run Code Online (Sandbox Code Playgroud)


Arp*_*rma 5

我面临着同样的问题,我用的onclick监听器,而不是听众的oncheck。那方式,当它被设置编程听者不会改变检查状态。在您的问题中,您应该尝试为复选框设置不同的检查更改侦听器。


小智 5

数据绑定非常简单

在xml复选框组件中

 <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onCheckedChanged="@{(compoundButton, checked) -> 
changeKeyboardVM.onCheckedChange(compoundButton, checked)}" />
Run Code Online (Sandbox Code Playgroud)

在ViewModel或Activity中

  public void onCheckedChange(CompoundButton button, boolean check) {
    Log.d("Z1D1", "onCheckedChange: " + check);
}
Run Code Online (Sandbox Code Playgroud)

现在true在选中和false未选中状态下进行布尔检查