1. Overview
Currently, DataBindings have three ways of customizing attributes.Namely:
- 1. xml introduces custom attribute labels.The code completes the binding with the @BindingAdapter annotation
- 2. Use directly in your code: @BindingMethods comment to introduce custom attributes and @BindingAdapter comment to complete the binding
- 3. When customizing control properties, providing a set method can automatically complete supporting databinding properties.Property Name = Control's custom property name (so sometimes it's found that no specific use of @BindingAdapter also supports databinding)
2. Instances
2.1. xml introduces custom attribute tags.The code completes the binding with the @BindingAdapter annotation
xml file:
<declare-styleable name="AdapterView"> <!--Can only be set at checkbox in--> <attr name="setCheckValue" format="boolean"/> </declare-styleable>
Code file:
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()); } }); } }
Note: When attr name is defined in xml, it is not possible to jump to the custom attribute when used in XML layout without format tag.Add to jump
The code here uses java code, which corresponds to a static function.There are several static ways to correspond to kotlin code:
2.1.1, for example, the outermost layer is written in kotlin's singleton, preceded by the @JvmStatic annotation:
For example:
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. Write with kotin's extension function:
For example, the code below
@BindingAdapter(value = ["labelCheckChecked"], requireAll = false) fun LabelCheckBoxView.setEnable(labelCheckChecked: Boolean) { this.getCheckBox().isChecked = labelCheckChecked }
2.1.3, kotlin also has a static way to write a function, which is programmed in a functional way, without a set of classes.
For example: demo on Google's official website
@BindingAdapter("android:paddingLeft") fun setPaddingLeft(view: View, padding: Int) { view.setPadding(padding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()) }
2.2, @BindingMethods + @BindingAdapter way
You don't need to write attributes in xml, just use code.Completion will also be prompted when using
@RestrictTo(RestrictTo.Scope.LIBRARY) @BindingMethods(BindingMethod(type = LabelCheckBoxView::class, attribute = "onCheckedChangedCommand", method = "setCheckedChanged"), BindingMethod(type = LabelCheckBoxView::class, attribute = "labelCheckChecked", method = "setEnable")) class ViewAdapter /** * Binding Change Event * 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. When customizing control properties, providing a set directly supports databinding
Custom properties:
<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) { /** * Left 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) } //Set stretch mode, left-right alignment if (a.hasValue(R.styleable.LabelCheckBoxView_labCheckSelect)) { switchLabel.isSelected = a.getBoolean(R.styleable.LabelCheckBoxView_labCheckSelect, false) } a.recycle() } tvLabelTip.text = tipStr } ... ... /** * This needs to be retained, supporting dataBinding with custom attributes * Desc: * <p> * Author: LiWei * Date: 2019-12-27 * @param str String */ fun setLabCheckTip(str: String) { tvLabelTip.text = str } /** * This needs to be retained, supporting dataBinding with custom attributes * Desc: * <p> * Author: LiWei * Date: 2019-12-27 * @param select Boolean */ fun setLabCheckSelect(select: Boolean) { switchLabel.isSelected = select } }
3. Reference
[1], Official https://developer.android.com/topic/libraries/data-binding/binding-adapters#kotlin
[2], androidx.databinding.adapters source code