android databinding 的三种自定义属性方式

1、概述

通过半年的使用发现,databinding 有三种自定义属性的方式。分别是:

  • 1、xml 引入自定义属性标签。代码通过 @BindingAdapter 注解完成绑定
  • 2、直接在代码里使用:@BindingMethods 注解引入自定义属性,再用@BindingAdapter 注解完成绑定
  • 3、自定义控件属性时,提供set的方法 可以自动完成支持 databinding 属性。 属性名字=控件的自定义属性名字 (所以有时候,发现没有特定使用@BindingAdapter 也支持了 databinding)

2、实例

2.1、xml 引入自定义属性标签。代码通过 @BindingAdapter 注解完成绑定

xml 文件:

<declare-styleable name="AdapterView">
  
  <attr name="setCheckValue" format="boolean"/>
declare-styleable>

代码文件:

public class ViewAdapter {
    @BindingAdapter({"setCheckValue"})
    public static void setCheckValue(final CheckBox checkBox, final ObservableField<Boolean> tags){
        tags.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
            @Override
            public void onPropertyChanged(Observable sender, int propertyId) {
                checkBox.setChecked(tags.get());
            }
        });
    }
}

注意: xml 里定义attr name的时候, 如果没有加上 format 标签, 在xml布局中使用的时候没法跳转到 自定义的这个属性。加了才可以跳转

这里代码使用的java的代码, java代码对应是static 静态函数。 对应kotlin代码 要用静态的方式 有几种方式:

2.1.1、比如最外层用kotlin的单例写, 方法前加 @JvmStatic 注解:

比如 :

object LinearLayoutViewAdapter {
 
    @JvmStatic
    @Suppress("UNCHECKED_CAST")
    @BindingAdapter(value = ["itemBinding", "items"], requireAll = false)
    fun <T> setAdapter(linearLayout: LinearLayout,
                       itemBinding: ItemBinding<T>?,
                       items: List<T>?) {
        requireNotNull(itemBinding) { "itemBinding == null" }
        val oldAdapter: BindingLinearLayoutAdapter<T>? = linearLayout.getAdapter() as? BindingLinearLayoutAdapter<T>
        val adapter = oldAdapter ?: BindingLinearLayoutAdapter()
        adapter.itemBinding = itemBinding
        adapter.setItems(items)
        if (adapter != oldAdapter) {
            linearLayout.setAdapter(adapter)
        }
    }
}
2.1.2、用 kotin的扩展函数来写:

比如 下文的代码

@BindingAdapter(value = ["labelCheckChecked"], requireAll = false)
fun LabelCheckBoxView.setEnable(labelCheckChecked: Boolean) {
    this.getCheckBox().isChecked = labelCheckChecked
}
2.1.3、kotlin 还有一种写静态的方法,是以函数式编程的方式,不套类,直接写一个函数。

比如:谷歌官网的demo写法

@BindingAdapter("android:paddingLeft")
    fun setPaddingLeft(view: View, padding: Int) {
        view.setPadding(padding,
                    view.getPaddingTop(),
                    view.getPaddingRight(),
                    view.getPaddingBottom())
    }

2.2、@BindingMethods + @BindingAdapter 的方式

不需要在xml中写属性,直接用代码。使用的时候 也会提示补全

@RestrictTo(RestrictTo.Scope.LIBRARY)
@BindingMethods(BindingMethod(type = LabelCheckBoxView::class, attribute = "onCheckedChangedCommand", method = "setCheckedChanged"),
        BindingMethod(type = LabelCheckBoxView::class, attribute = "labelCheckChecked", method = "setEnable"))
class ViewAdapter
 
 
/**
 * 绑定改变事件
 * Desc:
 * 

* Author: LiWei * Date: 2019-12-27 * @receiver LabelCheckBoxView * @param bindingCommand BindingCommand */ @BindingAdapter(value = ["onCheckedChangedCommand"], requireAll = false) fun LabelCheckBoxView.setCheckedChanged(bindingCommand: BindingCommand<Boolean>) { this.getCheckBox().setOnCheckedChangeListener { compoundButton, b -> bindingCommand.execute(b) } } @BindingAdapter(value = ["labelCheckChecked"], requireAll = false) fun LabelCheckBoxView.setEnable(labelCheckChecked: Boolean) { this.getCheckBox().isChecked = labelCheckChecked }

2.3、自定义控件属性时,提供set的方法 直接支持databinding
自定义属性:

<declare-styleable name="LabelCheckBoxView">
    <attr name="labCheckTip" format="string" />
    <attr name="labCheckSelect" format="boolean" />
declare-styleable>
 
class LabelCheckBoxView @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
 
    /**
     * 左边Tv
     */
    private var tipStr: String? = ""
 
 
    init {
        orientation = HORIZONTAL
        View.inflate(context, R.layout.widget_label_checkbox, this)
        if (attrs != null) {
            val a = getContext().obtainStyledAttributes(attrs, R.styleable.LabelCheckBoxView)
            if (a.hasValue(R.styleable.LabelCheckBoxView_labCheckTip)) {
                tipStr = a.getString(R.styleable.LabelCheckBoxView_labCheckTip)
            }
 
            //设置延展模式, 左右对齐方式
            if (a.hasValue(R.styleable.LabelCheckBoxView_labCheckSelect)) {
                switchLabel.isSelected = a.getBoolean(R.styleable.LabelCheckBoxView_labCheckSelect, false)
            }
 
            a.recycle()
        }
        tvLabelTip.text = tipStr
    }
 
...
...
 
    /**
     * 这个需要留着,用自定义属性支持 dataBinding
     * Desc:
     * 

* Author: xx * Date: 2019-12-27 * @param str String */ fun setLabCheckTip(str: String) { tvLabelTip.text = str } /** * 这个需要留着,用自定义属性支持 dataBinding * Desc: *

* Author: xx * Date: 2019-12-27 * @param select Boolean */ fun setLabCheckSelect(select: Boolean) { switchLabel.isSelected = select } }

3、参考
【1】、官网https://developer.android.com/topic/libraries/data-binding/binding-adapters#kotlin

【2】、androidx.databinding.adapters 源码

你可能感兴趣的:(android)