Android 数据绑定 - 观察封装在自定义视图中的编辑文本值

Android Data Binding - Observe edit text's value that is wrapped in custom view

我有一个包含编辑文本的自定义视图。

我希望使用数据绑定在使用此自定义视图的 class 处观察此编辑文本的变化。

如何将编辑文本的输入字符串公开给使用自定义视图的其他 classes?

双向数据绑定是唯一的方式吗?

其他XML:

<MyCustomView
        android:id="@+id/password_edittext"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:password="@={controller.password}"
        app:isPasswordValid="@={controller.isValid}"/>

自定义view的布局(Linear Layout):

<merge>

    <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/security_code_input_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/email_text_view">

        <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/security_code_edit_text"
                android:background="@drawable/edittext_background"
                android:inputType="textPassword"
                android:text="@={view.pass}"
                app:onSubmit="@{() -> view.onKeyboardActionDoneClicked()}" />

    </com.google.android.material.textfield.TextInputLayout>

    <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/textfield_error_invalid_password_length"
            app:visibleOrGone="@{view.showInvalidPasswordText}" />

</merge>

如果您想在您的示例中使用 xml 语法 (app:password="@=controller.password"),那么您需要使用 @BindingAdapter 和 [= 为双向数据绑定定义静态方法12=] 注释。您可以找到一个官方示例 here (though I prefer using top-level kotlin extension functions rather than nesting them in an object since it doesn't require the @JvmStatic annotation and feels more idiomatic). You can also check out the library source for how 2-way binding adapters are defined for TextView here,尽管它可能比您需要为您的案例做的更多。

如果您需要做的只是观察文本变化,而不需要直接在您的自定义视图上设置文本,那么双向数据绑定是不必要的,您可以设置某种类型的侦听器,当文本更改时会回调(如果您有 public setter,可以通过数据绑定设置)或公开您可以观察到的 LiveData<String> (不使用 xml/data 绑定)。

我可以想到两种方法

  • 使用绑定适配器:您可以将 viewModel 实例传递给绑定适配器。在您的绑定适配器中,您将观察到 editText 更改并调用任何 viewModel 的 public 方法,如下所示:
    @BindingAdapter("bind:doSomething")
    fun bindDoSomething(
        view: EditText,
        vm: ViewModel?
    ) {
        vm?.let {
            view.addTextChangedListener(object : TextWatcher {
                override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
                }

                override fun afterTextChanged(s: Editable?) {
                }

                override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
                    vm.callFun()
                }
            })
        }
    }

在你的 xml:

app:doSomething="@{vm}"
  • 使用传统界面方法:在自定义视图 class 和 activity/fragment 之间有一个界面。可以从自定义视图中实现的 TextChangedListener 的 onTextChanged 调用接口方法 class.

如果这对您有帮助或您有任何疑问,请告诉我