问题描述
我正在使用 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())
}