如何为Android中的双向数据绑定制作合适的绑定适配器

问题描述

我正在尝试在我的Android应用中制作一个页面,该页面允许用户在EditText中输入Float值并将该值绑定到我的视图模型。这是我当前绑定适配器的代码

import android.text.SpannableStringBuilder
import android.widget.EditText
import androidx.databinding.BindingAdapter
import androidx.databinding.InverseBindingAdapter

@BindingAdapter("android:text")
fun setText(view: EditText,value: Float?) {
    view.text = value?.let { SpannableStringBuilder(value.toString()) } ?: SpannableStringBuilder("")
}

@InverseBindingAdapter(attribute = "android:text",event = "android:textAttrChanged")
fun getTextString(view: EditText): Float? {
    val editTextString: String? = view.text?.toString()
    return if(editTextString == null || editTextString == "") 0.0f else editTextString.toString().toFloat()
}

这是我的布局文件中的EditText的代码

<com.google.android.material.textfield.TextInputLayout
            android:id="@+id/amount_edit_text_outer"
            style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
            android:layout_width="@dimen/edit_text_width"
            android:layout_height="@dimen/edit_text_height"
            android:layout_gravity="center"
            android:hint="@string/edit_text_hint"
            app:layout_constraintBottom_toTopOf="@+id/fab"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">

            <com.google.android.material.textfield.TextInputEditText
                android:id="@+id/amount_edit_text_inner"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:text="@={viewmodel.liveAmount$app_debug}"
                android:inputType="numberDecimal" />

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

最后,我的视图模型实时数据变量如下所示:

internal val liveAmount = mutablelivedata<Float>(0.0f)

我还应该补充一点,当我在手机上运行此代码时,它允许我在EditText中输入第一个数字,而没有其他输入。此外,除非我杀死该应用程序,否则键盘不会消失。欢迎任何问题或评论。谢谢大家的帮助!

解决方法

尝试更改此内容:

@InverseBindingAdapter(attribute = "android:text",event = "android:textAttrChanged")

收件人:

@InverseBindingAdapter(attribute = "android:text")

并添加其他方法:

// This notifies the data binding system that the attribute value has changed.
@BindingAdapter("android:textAttrChanged")
fun setTextChangedListener(editText: TextInputEditText,listener: InverseBindingListener) {
    editText.addTextChangedListener(object: TextWatcher{

        override fun beforeTextChanged(s: CharSequence?,start: Int,count: Int,after: Int) {
        }

        override fun onTextChanged(s: CharSequence?,before: Int,count: Int) {
        }

        override fun afterTextChanged(s: Editable?) {
            listener.onChange()
        }
    })
}

这未经测试,但它应该可以工作或至少可以接近。参见此处,了解其他类似示例:

https://github.com/gavingt/upcoming-games/blob/adc8b7e67b1e05d7bc9ac6247b82cfa93a43a26f/app/src/main/java/com/gavinsappcreations/upcominggames/utilities/BindingAdapters.kt#L324