带有TextWatcher和LiveData的EditText中的光标位置?
Posted
技术标签:
【中文标题】带有TextWatcher和LiveData的EditText中的光标位置?【英文标题】:Cursor position in EditText with TextWatcher and LiveData? 【发布时间】:2021-08-15 13:26:46 【问题描述】:我正在使用 kotlin 在 android 应用程序上创建一个表单。表单的每个字段都与一个 livedata 相关联,以立即验证或更新数据。为了获得这个结果,我使用了一个 textwatcher,它会在每次文本更改时更新关联的 livedata。问题是每次更新时,它会将光标放在字段的开头,从而无法连续写入。
我把代码中有趣的部分贴在这里:
活动
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?, start: Int, 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_
android:layout_>
<EditText
android:id="@+id/nameEditText"
android:layout_
android:layout_
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_
android:layout_>
<EditText
android:id="@+id/priceEditText"
android:layout_
android:layout_
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 ());' 但效果不佳,因为如果我在字符串中间进行更改,它会带来光标到最后。即使在双字段中,它的行为也不正确。 我需要让光标始终在准确的位置?在字符串中间添加、删除或写入的情况下。无论是字符串还是双精度。
有人可以帮我吗?
感谢您的耐心和帮助!
【问题讨论】:
【参考方案1】:这种情况正在发生,因为在您的 ViewModel 观察者中,您将 nameValue 和 priceValue 设置回它们刚刚来自的 EditText。您可以添加一个检查并且不将未更改的值设置回 EditText:
if ((nameValue?.toString() == binding.nameEditText.getText().toString()) == false)
binding.nameEditText.setText(nameValue?.toString())
【讨论】:
不,我不能停止观察 nameValue 和 priceValue,因为我还有其他字段与这些值相关联。【参考方案2】:我也有同样的问题,光标移到开头,搜索我找到了第一个解决方案,在一定程度上可以让我连续写一条消息,如下
viewModel.name.observe(lifecycleOwner, Observer nameValue->
binding.nameEditText.setText(
nameValue?.toString()
)
binding.nameEditText.setSelection(
nameValue?.toString().length
)
)
我以为我已经解决了,但是出现了另一个问题,那就是如果我想在输入字符后编辑中心的任何部分,光标会移动到最后,直到找到正确的解决方案https://***.com/a/65794745/15798571
viewModel.name.observe(lifecycleOwner, Observer nameValue->
val selection = binding.nameEditText.selectionEnd
val length = nameValue.length
binding.nameEditText.setText(
nameValue?.toString()
)
binding.nameEditText.setSelection(
Math.min(selection, length)
)
)
我希望它能像它为我一样为你服务
【讨论】:
以上是关于带有TextWatcher和LiveData的EditText中的光标位置?的主要内容,如果未能解决你的问题,请参考以下文章
Edittext textwatcher触发listview中的所有editexts