首页 > 解决方案 > Android:具有双向绑定的复合或自定义视图

问题描述

我想在 Android 中创建可以绑定变量的自定义或复合视图(几个标准组件的组合)。

这是一个简单的短示例:

新控件 (view_custom.xml)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

        <EditVext android:id="@+id/edittext_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" android:textStyle="bold"  android:layout_gravity="center" />
        <EditVext 
        ...
</LinearLayout>

我想在我的片段中使用双向绑定的控件

<com.test.controls.CustomView
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            app:title="@={viewmodel.title}"
                            />

我试图像这样创建 attr

    <declare-styleable name="Custom">
      <attr name="title" format="string" />
</declare-styleable>

class CustomView(context: Context, attributeSet: AttributeSet?) :
    LinearLayout(context, attributeSet) {
          init {
    val a = context.obtainStyledAttributes(attributeSet, R.styleable.CustomView, 0, 0)
    val titleText = a.getString(R.styleable.CustomView_titl

    val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
    inflater.inflate(R.layout.view_custom, this, true)

    edittext_title.text = titleText

    }

  fun setTitle(title String) {
    edittext_title.text = title
    }

    fun getTitleText(): String {
    return edittext_title.text.toString()
    }
}

单向绑定有效,但双向绑定无效。

标签: androidkotlindata-binding

解决方案


这是我的解决方案。

我创建了一个界面来通知“标题”变量已更改

interface TwoWayBindingListener {
    fun hasChanged()
}

然后我扩展了我的 CustomView 类

private var listener: TwoWayBindingListener? = null

fun addListener(twoWayBindingListener: TwoWayBindingListener) {
    listener = twoWayBindingListener
}

并在我更改 mit 控件中的标题时调用 hasChanged 方法

listener?.hasChanged()

我添加了这些 BindingAdapters

@BindingAdapter("title")
fun set#String(customView: CustomView, t: String?) {
    if (t == null) {
    return
    }
    customView.setTitle()
}

@InverseBindingAdapter(attribute = "title", event = "titleAttrChanged")
fun getDateString(customView: CustomView): String {
    return customView.getTitle()
}

@BindingAdapter("titleAttrChanged")
fun setListener(customView: CustomView, listener: InverseBindingListener?) {
    if (listener != null) {
    customView.addListener(
        object : TwoWayBindingListener {
        override fun hasChanged() {
            listener.onChange()
        }
        })
    }
}

推荐阅读