通过半年的使用发现,databinding 有三种自定义属性的方式。分别是:
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代码 要用静态的方式 有几种方式:
比如 :
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)
}
}
}
比如 下文的代码
@BindingAdapter(value = ["labelCheckChecked"], requireAll = false)
fun LabelCheckBoxView.setEnable(labelCheckChecked: Boolean) {
this.getCheckBox().isChecked = labelCheckChecked
}
比如:谷歌官网的demo写法
@BindingAdapter("android:paddingLeft")
fun setPaddingLeft(view: View, padding: Int) {
view.setPadding(padding,
view.getPaddingTop(),
view.getPaddingRight(),
view.getPaddingBottom())
}
不需要在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 源码