Author: BuildF
preface
The default reader of this article has a certain understanding of databinding. If you don't know much, you can see Dongge's Full instructions for DataBinding , many people reject databinding, but others like it. Although it is controversial, it does not prevent us from learning and understanding.
This article describes how to bind data in both directions with a custom view to realize the effect of app:customvalue="@={userName}" using customization in xml
app:xx = "@{userName}" one-way binding
app:xx = "@ = {userName}" bidirectional binding
Introducing databinding
1. First step
Introduce kapt plug-in
2. Step two
Open data binding (here is the difference between the new version of gradle and the old version, and tell me which version it is in the comment area where you know it) the new version of gradle
buildFeatures.dataBinding = true
Old gradle
android{ /.../ dataBinding { enabled = true; } }
Implementation code
The implementation method provided here is certainly not the optimal solution, or the best, but it is more suitable as a small piece of knowledge
1. Let me show you the catalogue of the whole project first
2. First, create a CustomView with a TextView and EditText as a demonstration.
class CustomView(mContext: Context, attributeSet: AttributeSet?) : LinearLayout(mContext, attributeSet) { private var onChangeListener: InverseBindingListener? = null private var onInputChangeListener: InverseBindingListener? = null private var itemInput: EditText? = null private var itemText: TextView? = null var etInput = "" set(value) { val oldValue = field if (value == oldValue) { return; } field = value onInputChangeListener?.onChange() } var tvValue = "" set(value) { val oldValue = field if (value == oldValue) { return; } field = value onChangeListener?.onChange() } init { initView(mContext, attributeSet) } private fun initView(mContext: Context, attributeSet: AttributeSet?) { val view = inflate(mContext, R.layout.widget_custom_view, this) itemInput = view.findViewById(R.id.et_input) itemText = view.findViewById(R.id.tv_value) itemText?.setOnClickListener { tvValue = System.currentTimeMillis().toString() itemText?.text = tvValue } itemInput?.doOnTextChanged { text, start, before, count -> etInput = text.toString() } } internal fun setOnInputChangeListener(listener: InverseBindingListener) { if (onInputChangeListener == null) { this.onInputChangeListener = listener } } internal fun setOnValueChangeListener(listener: InverseBindingListener) { if (onChangeListener == null) { this.onChangeListener = listener } } }
widget_custom_view.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="100dp" android:orientation="vertical"> <TextView android:id="@+id/tv_value" android:layout_width="match_parent" android:layout_height="50dp" android:background="@color/purple_200" android:gravity="center" android:hint="Please select" android:textColor="@color/white" android:textColorHint="@color/white" android:textSize="16dp" /> <EditText android:id="@+id/et_input" android:layout_width="match_parent" android:layout_height="50dp" android:background="@color/teal_700" android:gravity="center" android:hint="Please enter" android:textColor="@color/white" android:textColorHint="@color/white" android:textSize="16dp" /> </LinearLayout>
3. Create a BindAdapter management class DatabindComponent class to manage related usage, or write the code in CustomView through BindMethod
object DataBindComponent { @BindingAdapter("itemInput") @JvmStatic fun CustomView.setItemInputParams(value: String) { etInput = value } @InverseBindingAdapter(attribute = "itemInput", event = "itemInputAttrChanged") @JvmStatic fun getItemInputParams(view: CustomView): String { return view.etInput } @BindingAdapter(value = ["itemInputAttrChanged"], requireAll = false) @JvmStatic fun CustomView.itemPutChange(textAttrChanged: InverseBindingListener) { setOnInputChangeListener(textAttrChanged) } @BindingAdapter("itemValue") @JvmStatic fun CustomView.setItemValueParams(value: String) { tvValue = value } @InverseBindingAdapter(attribute = "itemValue", event = "itemValueAttrChanged") @JvmStatic fun getItemValueParams(view: CustomView): String { return view.tvValue } @BindingAdapter(value = ["itemValueAttrChanged"], requireAll = false) @JvmStatic fun CustomView.itemValueChange(textAttrChanged: InverseBindingListener) { setOnValueChangeListener(textAttrChanged) } }
4. Add CustomView in xml and two observablefields to listen and bind data
summary
The reason why GitHub code warehouse is not posted is that these sample codes are written in the project through Moudle, and some of them are not suitable for release. All the key codes are released, and only some used codes are displayed in the form of pictures. If you just need to bind the custom view in two directions, the above example can help you. If you have a better writing method, you can tell me in the comment area and let me learn