芯片组 2路绑定适配器

6

我希望创建ChipGroup的双向绑定适配器。我复制了默认的RadioGroup绑定适配器并进行了一些更改,但它不能同时工作。如果以编程方式将数据设置到可观察对象中,ChipGroup会从中检索更改。但是手动选择芯片不会将更改设置为可观察对象。

这是我的适配器:

@InverseBindingMethods(InverseBindingMethod(type = ChipGroup::class, attribute = "android:checkedButton", method = "getCheckedRadioButtonId"))
class ChipGroupBindingAdapter {
companion object {
    @JvmStatic
    @BindingAdapter("android:checkedButton")
    fun setCheckedChip(view: ChipGroup?, id: Int) {
        if (id != view?.checkedChipId) {
            view?.check(id)
        }
    }

    @JvmStatic
    @BindingAdapter(value = ["android:onCheckedChanged", "android:checkedButtonAttrChanged"], requireAll = false)
    fun setChipsListeners(view: ChipGroup?, listener: ChipGroup.OnCheckedChangeListener?,
                          attrChange: InverseBindingListener?) {
        if (attrChange == null) {
            view?.setOnCheckedChangeListener(listener)
        } else {
            view?.setOnCheckedChangeListener { group, checkedId ->
                listener?.onCheckedChanged(group, checkedId)
                attrChange.onChange()
                }
            }
        }
    }
}

布局文件:

<android.support.design.chip.ChipGroup
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:checkedButton="@{viewModel.checkedBtnObs}"
        app:singleSelection="true">

        <android.support.design.chip.Chip
            android:id="@+id/first_chip"
            style="@style/Widget.MaterialComponents.Chip.Choice"
            android:layout_width="110dp"
            android:layout_height="wrap_content"
            android:checkable="true"
            android:text="@string/month_12"
            app:chipBackgroundColor="@drawable/chip_background_selector" />

        <android.support.design.chip.Chip
            android:id="@+id/second_chip"
            style="@style/Widget.MaterialComponents.Chip.Choice"
            android:layout_width="110dp"
            android:layout_height="wrap_content"
            android:checkable="true"
            android:text="@string/month_6"
            android:textAlignment="center"
            app:chipBackgroundColor="@drawable/chip_background_selector" />

        <android.support.design.chip.Chip
            android:id="@+id/third_chip"
            style="@style/Widget.MaterialComponents.Chip.Choice"
            android:layout_width="110dp"
            android:layout_height="wrap_content"
            android:checkable="true"
            android:text="@string/month_1"
            app:chipBackgroundColor="@drawable/chip_background_selector" />

    </android.support.design.chip.ChipGroup>

并且可观察的:

val checkedBtnObs = ObservableInt(R.id.second_chip)
3个回答

7

最终,我找到了解决方案。 InverseBindingMethod 方法应该是 getCheckedChipId 而不是 getCheckedRadioButtonId

此外,@= 应该添加到xml中的 android:checkedButton="@{viewModel.checkedBtnObs}" ,就像这样 android:checkedButton="@={viewModel.checkedBtnObs}"

现在,这个适配器可以用于 ChipGroup 的双向绑定。

@InverseBindingMethods(InverseBindingMethod(type = ChipGroup::class, attribute = "android:checkedButton", method = "getCheckedChipId"))
class ChipGroupBindingAdapter {
companion object {
    @JvmStatic
    @BindingAdapter("android:checkedButton")
    fun setCheckedChip(view: ChipGroup?, id: Int) {
        if (id != view?.checkedChipId) {
            view?.check(id)
        }
    }

    @JvmStatic
    @BindingAdapter(value = ["android:onCheckedChanged", "android:checkedButtonAttrChanged"], requireAll = false)
    fun setChipsListeners(view: ChipGroup?, listener: ChipGroup.OnCheckedChangeListener?,
                          attrChange: InverseBindingListener?) {
        if (attrChange == null) {
            view?.setOnCheckedChangeListener(listener)
        } else {
            view?.setOnCheckedChangeListener { group, checkedId ->
                listener?.onCheckedChanged(group, checkedId)
                attrChange.onChange()
                }
            }
        }
    }
}

2

我成功地使用了DataBindingChipGroup,并且按照推荐的方式使用了InverseDataBinding。如果有人想知道我的实现方式,请看下面的代码:

SomeBindingAdapters.kt:

...
object PropertyTypeFilterBindingAdapters {
    @BindingAdapter("propertyTypeFilter")
    @JvmStatic
    fun ChipGroup.bindPropertyTypeFilter(marsApiFilter: MarsApiFilter?) =
        marsApiFilter?.let { filter ->
            when (filter) {
                MarsApiFilter.ALL -> check(R.id.filter_all_properties_chip)
                MarsApiFilter.RENT -> check(R.id.filter_properties_for_rent_chip)
                MarsApiFilter.BUY -> check(R.id.filter_properties_for_buy_chip)
            }
        }

    @InverseBindingAdapter(attribute = "propertyTypeFilter")
    @JvmStatic
    fun ChipGroup.convertToMarsApiFilter(): MarsApiFilter = when (checkedChipId) {
        R.id.filter_properties_for_rent_chip -> MarsApiFilter.RENT
        R.id.filter_properties_for_buy_chip -> MarsApiFilter.BUY
        else -> MarsApiFilter.ALL
    }

    @BindingAdapter("propertyTypeFilterAttrChanged")
    @JvmStatic
    fun ChipGroup.setListeners(attrChange: InverseBindingListener?) =
        setOnCheckedChangeListener { _, _ -> attrChange?.onChange() }
}
...
  • MarsApiFilter 是一个针对我的具体情况的枚举类。

some_layout.xml:

...
<com.google.android.material.chip.ChipGroup
    android:id="@+id/filter_property_type_chip_group"
    ...
    bind:propertyTypeFilter="@={viewModel.propertyTypeFilter}"
    >

    <com.google.android.material.chip.Chip
        android:id="@+id/filter_all_properties_chip"
        ...
        />

    <com.google.android.material.chip.Chip
        android:id="@+id/filter_properties_for_rent_chip"
        ...
        />

    <com.google.android.material.chip.Chip
        android:id="@+id/filter_properties_for_buy_chip"
        ...
        />
</com.google.android.material.chip.ChipGroup>
...
  • bind只是一个被声明为常规命名空间的花哨命名空间:xmlns:bind="http://schemas.android.com/apk/res-auto"

SomeViewModel.kt:

...
val propertyTypeFilter = MutableLiveData<MarsApiFilter>().apply { value = MarsApiFilter.ALL }
...

如果你想使用 ChipGroup 的 setOnCheckedChangeListener() 方法,那么重要的是你需要设置 app:singleSelection="true"。 - Hasan Kucuk

0
if (attrChange == null) {
            view?.setOnCheckedChangeListener(listener)
        } else {
            view?.setOnCheckedChangeListener { group, checkedId ->
                listener?.onCheckedChanged(group, checkedId)
                attrChange.onChange()
                }
            }
        }

或许应该是

if (listener != null) {
            view?.setOnCheckedChangeListener(listener)
        } else {
            view?.setOnCheckedChangeListener { group, checkedId ->
                listener?.onCheckedChanged(group, checkedId)
                attrChange.onChange()
                }
            }
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接