Databinding custom view two-way binding for Android developers

Get into the habit of writing together! This is the third day of my participation in the "Nuggets Daily New Plan · April Update Challenge", click to view the details of the event .

foreword

The default readers of this article have already had a certain understanding of databinding. If you don't know much, you can look at the most complete instructions for using DataBinding. Many people reject databinding, but some people like to use it. Although it is controversial, it does not prevent us from learning and understanding.
This article is about how a custom view binds data in both directions, so that using customization in xml can also achieve the effect of app:customvalue="@={userName}"

app:xx="@{userName}" one-way binding
app:xx="@={userName}" two-way binding

Introduce Databingding

1. The first step is
to introduce the kapt plugin image.png. 2. The second step is to
enable databinding (here is the difference between the new version of gradle and the old version, which version is the specific version, and someone who knows it will tell me in the comment area) The new version of gradle

buildFeatures.dataBinding = true
复制代码

image.pngold version of gradle

android{
/.../ 
    dataBinding { 
        enabled = true;
    } 
}
复制代码

implementation code

The implementation method provided here is definitely not the optimal solution, or the best, but it is more suitable as a little knowledge to attract others.

1. Let's take a look at the directory of the entire project

image.png

2. First, create a new 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="请选择"
    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="请输入"
    android:textColor="@color/white"
    android:textColorHint="@color/white"
    android:textSize="16dp" />
</LinearLayout>
复制代码

3. Create a new BindAdapter management class DatabindComponent class to manage related usage, or write the code in it in CustomView by 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 add two ObservableFields for data monitoring and binding

image.png

image.png

Summarize

The reason why the GitHub code repository is not posted is because 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 happen to have the need to bind custom views in both directions, the above example can completely help you. If you have a better way of writing, you can tell me in the comment area and let me learn

Guess you like

Origin juejin.im/post/7086001692860219428