带有 TextWatcher 和 LiveData 的 EditText 中的光标位置?

问题描述

我正在使用 kotlin 在 android 应用程序上创建表单。表单的每个字段都与一个实时数据相关联,以立即验证或更新数据。为了获得这个结果,我使用了一个 textwatcher,它在文本的每次更改时更新相关的实时数据。问题是每次更新时,它都会将光标放在字段的开头,从而无法连续写入。

在这里粘贴代码的有趣部分:

活动

     viewmodel.name.observe(lifecycleOwner,Observer { nameValue->
            binding.nameEditText.setText(
                nameValue?.toString()
            )
            binding.nameTextInputLayout.error =
                viewmodel.nameError.value
        })
     viewmodel.price.observe(lifecycleOwner,Observer { priceValue->
            binding.priceEditText.setText(
                price?.toString()
            )
            binding.priceTextInputLayout.error =
                viewmodel.priceError.value
        })

binding.nameEditText.addTextChangedListener(
        TextFieldValidation(
            binding.nameEditText
        )
    )
binding.priceEditText.addTextChangedListener(
        TextFieldValidation(
            binding.priceEditText
        )
    )


  inner class TextFieldValidation(private val view: View) : TextWatcher {
        override fun afterTextChanged(s: Editable?) {}
        override fun beforeTextChanged(s: CharSequence?,start: Int,count: Int,after: Int) {}
        override fun onTextChanged(s: CharSequence?,before: Int,count: Int) {

            when (view.id) {
                R.id.nameEditText-> {
                    viewmodel.onNameChanged(s.toString())
                    viewmodel.isNameValid()
                }
                R.id.priceEditText-> {
                    viewmodel.onPriceChanged(s.toString())
                    viewmodel.isPriceValid()
                }
     }
}

视图模型

var name = mutablelivedata<String>()
var price = mutablelivedata<Double>()

var nameError = mutablelivedata<String>()
var priceError = mutablelivedata<String>()

fun onNameChanged(newValue: String?) {
    if ((name.value != newValue)) {
        name.value = newValue
    }
}
fun onPriceChanged(newValue: Double?) {
    if ((price.value != newValue)) {
        price.value = newValue
    }
}

fun isNameValid() : Boolean {

    return if ((name.value == null) || (name.value == "")) {
        nameError.value = "Error"
        false
    } else {
        nameError.value = ""
        true
    }
}
fun isPriceValid() : Boolean {

    return if ((price.value == null) || (price.value == "")) {
        priceError.value = "Error"
        false
    } else {
        priceError.value = ""
        true
    }
}

XML

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

            android:id="@+id/nameTextInputLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <EditText
                android:id="@+id/nameEditText"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_centerHorizontal="true"
                android:layout_centerVertical="true"
                android:backgroundTint="@color/white"
                android:inputType="text" />
        </com.google.android.material.textfield.TextInputLayout>

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

            android:id="@+id/priceTextInputLayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <EditText
                android:id="@+id/priceEditText"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_centerHorizontal="true"
                android:layout_centerVertical="true"
                android:backgroundTint="@color/white"
                android:inputType="numberDecimal" />
        </com.google.android.material.textfield.TextInputLayout>

我尝试使用 'mEdittext.setSelection (mEdittext.length ());'效果不佳,因为如果我在字符串中间进行更改,它会带光标到最后。即使在双字段中,它的行为也不正确。 我需要让光标始终处于准确位置吗?在字符串中间添加删除或写入的情况下。无论是字符串还是双精度。

有人可以帮我吗?

感谢您的耐心和帮助!

解决方法

这正在发生,因为在您的 ViewModel 观察者中,您将 nameValue 和 priceValue 设置回它们刚刚来自的 EditText。您可以添加一个检查,而不是将未更改的值设置回 EditText:

if ((nameValue?.toString() == binding.nameEditText.getText().toString()) == false) {
   binding.nameEditText.setText(nameValue?.toString())
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...