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.
如果这对您有帮助或您有任何疑问,请告诉我
我有一个包含编辑文本的自定义视图。
我希望使用数据绑定在使用此自定义视图的 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.
如果这对您有帮助或您有任何疑问,请告诉我