【问题标题】:Cursor position in EditText with TextWatcher and LiveData?带有TextWatcher和LiveData的EditText中的光标位置?
【发布时间】: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_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 ());' 但效果不佳,因为如果我在字符串中间进行更改,它会带来光标到最后。即使在双字段中,它的行为也不正确。 我需要让光标始终在准确的位置?在字符串中间添加、删除或写入的情况下。无论是字符串还是双精度。

有人可以帮我吗?

感谢您的耐心和帮助!

【问题讨论】:

    标签: android android-edittext onchange android-livedata textwatcher


    【解决方案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://stackoverflow.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)
        )
    })
    

    我希望它能像它为我一样为你服务

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多