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">
  <!--只能设置在 checkbox 中-->
  <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:
 * <p>
 * Author: LiWei
 * Date: 2019-12-27
 * @receiver LabelCheckBoxView
 * @param bindingCommand BindingCommand<Boolean>
 */
@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:
     * <p>
     * Author: xx
     * Date: 2019-12-27
     * @param str String
     */
    fun setLabCheckTip(str: String) {
        tvLabelTip.text = str
    }
 
    /**
     * 这个需要留着,用自定义属性支持 dataBinding
     * Desc:
     * <p>
     * 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 源码

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以通过在自定义控件的布局文件使用 `<layout>` 标签来启用 DataBinding,然后在代码使用 DataBindingUtil 类来绑定数据。 例如,假设我们有一个自定义控件 MyCustomView,它的布局文件为 custom_view.xml,我们想要绑定一个名为 `text` 的字符串属性。我们可以这样做: 1. 在 custom_view.xml 使用 `<layout>` 标签包裹布局文件的根布局: ```xml <layout xmlns:android="http://schemas.android.com/apk/res/android"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <!-- 自定义控件的布局 --> </LinearLayout> </layout> ``` 2. 在 MyCustomView 的构造函数使用 DataBindingUtil.inflate 方法来获取绑定对象,并将它与自定义控件的根布局绑定: ```java public MyCustomView(Context context, AttributeSet attrs) { super(context, attrs); // 获取绑定对象 CustomViewBinding binding = DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.custom_view, this, true); // 绑定数据 binding.setText("Hello, world!"); } ``` 3. 在 MyCustomView 添加一个 `text` 属性,并在 custom_view.xml 使用 `@{}` 语法来绑定该属性: ```java public class MyCustomView extends LinearLayout { private String text; public MyCustomView(Context context, AttributeSet attrs) { super(context, attrs); CustomViewBinding binding = DataBindingUtil.inflate(LayoutInflater.from(context), R.layout.custom_view, this, true); binding.setCustomView(this); } public String getText() { return text; } public void setText(String text) { this.text = text; } } ``` ```xml <layout xmlns:android="http://schemas.android.com/apk/res/android"> <data> <variable name="customView" type="com.example.MyCustomView" /> </data> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{customView.text}" /> </LinearLayout> </layout> ``` 这样,当 MyCustomView 的 `text` 属性发生变化时,custom_view.xml 的 TextView 的文本也会自动更新。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值