【问题标题】:ChipGroup 2-way binding adapterChipGroup 2 路绑定适配器
【发布时间】:2018-09-14 09:46:14
【问题描述】:

我想创建 ChipGroup 2 路绑定适配器。我已经复制了默认的 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)

【问题讨论】:

    标签: android kotlin android-databinding android-chips


    【解决方案1】:

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

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

    现在这个适配器可以用于 ChipGroup 2-way binding

    @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】:

      我得到ChipGroupDataBinding 按预期工作并使用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" 重要!!!
      【解决方案3】:
      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()
                      }
                  }
              }
      

      【讨论】:

        猜你喜欢
        • 2020-12-20
        • 1970-01-01
        • 2019-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-28
        • 1970-01-01
        相关资源
        最近更新 更多