带有 TextWatcher 和 LiveData 的 EditText 中的光标位置? [英] Cursor position in EditText with TextWatcher and LiveData?

查看:104
本文介绍了带有 TextWatcher 和 LiveData 的 EditText 中的光标位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm creating a form on an android application using kotlin. Each field of the form is associated with a livedata, to validate or update the data instantly. To obtain this result, I used a textwatcher, which updates the associated livedata at each change of the text. The problem is that with each update, it places the cursor at the start of the field making it impossible to write continuously.

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

I paste here the intresting part of the code:

活动

     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_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 ());' 但效果不佳,因为如果我在字符串中间进行更改,它会带光标到最后.即使在双字段中,它的行为也不正确.我需要让光标始终处于准确位置吗?在字符串中间添加、删除或写入的情况下.无论是字符串还是双精度.

I tried using 'mEdittext.setSelection (mEdittext.length ());' but it doesn't work well, because if I make changes in the middle of the string, it brings the cursor to the end. And even in double fields, it doesn't behave correctly. I need to have the cursor always at the exact position? Either in case of adding, deleting or writing in the middle of the string. And both in the case of a string and in the case of a double.

有人可以帮我吗?

感谢您的耐心和帮助!

推荐答案

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

This is happening, because in your ViewModel observer you are setting nameValue and priceValue back to the EditText where they just came from. You could add a check and not set unchanged values back to the EditText:

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

这篇关于带有 TextWatcher 和 LiveData 的 EditText 中的光标位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆