Android:单向绑定使Switch OnCheckedChangeListener不起作用

时间:2019-02-27 03:56:35

标签: android data-binding

我只是对这种情况感到好奇,对单向绑定的真正工作方式感到好奇。

我有一个Switch和2个文本视图,它们的颜色与Switch的选中状态绑定在一起

<TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clickable="true"
                android:focusable="true"
                android:textColor="@{swLanguage.checked ? @color/term_condition_gray_1 : @color/term_condition_green_1}"
                android:textSize="@dimen/_10ssp" />

            <Switch
                android:id="@+id/swLanguage"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/_8sdp"
                android:layout_marginRight="@dimen/_8sdp"
                android:thumb="@drawable/term_condition_switch_thumb"
                android:track="@drawable/term_condition_switch_track" />


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:clickable="true"
                android:focusable="true"
                android:textColor="@{swLanguage.checked ? @color/term_condition_green_1 : @color/term_condition_gray_1}"
                android:textSize="@dimen/_10ssp" />

当Java代码中Switch的检查状态更改时,我想做一些额外的动作。但是只要在XML代码中将2个文本视图的颜色与开关的状态绑定在一起,setOnCheckedChangeListener就无法正常工作。

那么这是数据绑定功能本身的问题还是我只是不知道数据绑定是如何工作的?

1 个答案:

答案 0 :(得分:0)

您可以将ObservableBoolean与双向绑定连接。

XML

function startAnimation() { 
  var frames = document.getElementById("animation").children;
  var frameCount = frames.length;
  var i = 0;
  setInterval(function () { 
    frames[i % frameCount].style.display = "none";
    frames[++i % frameCount].style.display = "block";
}, 300);
}

活动

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">

    <data>
        <variable
            name="activity"
            type="someActivity"/>
    </data>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:clickable="true"
            android:focusable="true"
            android:textColor="@{activity.languageChecked ? @color/term_condition_gray_1 : @color/term_condition_green_1}"
            android:textSize="@dimen/_10ssp" />

        <Switch
            android:id="@+id/swLanguage"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/_8sdp"
            android:layout_marginRight="@dimen/_8sdp"
            android:checked="@={activity.languageChecked}"
            android:thumb="@drawable/term_condition_switch_thumb"
            android:track="@drawable/term_condition_switch_track" />


        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:clickable="true"
            android:focusable="true"
            android:textColor="@{activity.languageChecked ? @color/term_condition_green_1 : @color/term_condition_gray_1}"
            android:textSize="@dimen/_10ssp" />
    </LinearLayout>
</layout>

它如何工作?

  1. 如果更改了开关的检查状态,则public ObservableBoolean languageChecked = new ObservableBoolean(false) 变量将更改。
  2. 如果更改了languageChecked变量,则DataBinding的内部过程会将languageChecked的更改反映到所有绑定对象(在本例中为两个languageChecked

您可以在Java代码中更改'languageChecked'变量,还可以使用textview观察该变量的变化

---编辑---

如果您不通过ObservableBoolean和开关本身的addOnPropertyChangedCallback属性使用双向绑定,则DataBinding将使用InverseBinding来实现此目的。

构建成功后,您可以在Binding Object中观看编写的代码。 (在这种情况下,我的布局名称是test_layout,所以类名称是TestLayoutBindingImpl,因为我使用了DataBindingV2)

checked

在最后一条语句中,他们使用// Inverse Binding Event Handlers private androidx.databinding.InverseBindingListener swLanguageandroidCheckedAttrChanged = new androidx.databinding.InverseBindingListener() { @Override public void onChange() { synchronized(TestLayoutBindingImpl.this) { mDirtyFlags |= 0x2 L; } requestRebind(); } }; if ((dirtyFlags & 0x6 L) != 0) { // read swLanguage.checked swLanguageChecked = swLanguage.isChecked(); if ((dirtyFlags & 0x6 L) != 0) { if (swLanguageChecked) { dirtyFlags |= 0x10 L; dirtyFlags |= 0x40 L; } else { dirtyFlags |= 0x8 L; dirtyFlags |= 0x20 L; } } // read swLanguage.checked ? @android:color/term_condition_gray_1 : @android:color/term_condition_green_1 swLanguageCheckedMboundView1AndroidColorTermConditionGray1MboundView1AndroidColorTermConditionGreen1 = ((swLanguageChecked) ? (getColorFromResource(mboundView1, R.color.term_condition_gray_1)) : (getColorFromResource(mboundView1, R.color.term_condition_green_1))); // read swLanguage.checked ? @android:color/term_condition_green_1 : @android:color/term_condition_gray_1 swLanguageCheckedMboundView2AndroidColorTermConditionGreen1MboundView2AndroidColorTermConditionGray1 = ((swLanguageChecked) ? (getColorFromResource(mboundView2, R.color.term_condition_green_1)) : (getColorFromResource(mboundView2, R.color.term_condition_gray_1))); } // batch finished if ((dirtyFlags & 0x6 L) != 0) { // api target 1 this.mboundView1.setTextColor(swLanguageCheckedMboundView1AndroidColorTermConditionGray1MboundView1AndroidColorTermConditionGreen1); this.mboundView2.setTextColor(swLanguageCheckedMboundView2AndroidColorTermConditionGreen1MboundView2AndroidColorTermConditionGray1); } if ((dirtyFlags & 0x4 L) != 0) { // api target 1 androidx.databinding.adapters.CompoundButtonBindingAdapter.setListeners(this.swLanguage, (android.widget.CompoundButton.OnCheckedChangeListener) null, swLanguageandroidCheckedAttrChanged); } 方法向setListeners()注册OnCheckedChangeListener()。 swLanguageandroidCheckedAttrChanged使用InverseBindingAdapter观察更改。

由于swLanguageandroidCheckedAttrChanged使用setListener()方法来设置侦听器,因此您无法在绑定对象和Java代码之间的代码中操作两个setOnCheckedChangeListener

因此,如果要在Java代码(活动)中使用setOnCheckedChangeListener,请使用ObservableBoolean并通过setOnCheckedChangeListener观察更改。

如果要比较两个解决方案的结果,请参见Gist