如何防止用户删除 EditText 小部件中预先存在的文本?
How can I prevent a user from deleting pre-existing text in an EditText widget?
我有一个 EditText
,其中包含一些不得删除的预先存在的文本。应该只允许用户在视图中追加文本。
我现在的解决方案如下所示,我检查 EditText
的新长度是否比原始文本短。如果是,则用户试图删除一个字符,所以我只需用原始文本重新填充视图并移动光标。这个解决方案的问题是用户可以输入比原始长度更长的文本,然后将光标的位置更改为原始文本中的某个位置,最后删除字符。
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val originalText = "Hello"
binding.et.setText(originalText)
binding.et.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
s?.let {
if (s.length < originalText.length) {
binding.et.setText(originalText)
binding.et.setSelection(originalText.count())
}
}
}
override fun afterTextChanged(s: Editable?) {}
})
}
我该怎么办?我对所有想法持开放态度。
谢谢!
编辑:
我也试过组合 EditText
和 TextView
(正如一些人所建议的那样)但是布局很难实现,因为原始文本和新文本都可以跨越多行.我上面的解决方案在原文中包含一个单词,但可能有很多。所以我需要迎合这种情况:
...其中白色框代表 TextView
,红色框代表 EditText
。
我认为 Bö macht Blau 的回答也不会奏效,因为前缀在它自己的“列”中。
我想我将不得不使用 Zain 的解决方案 (startsWith()
) 或创建自定义视图(尽管我以前从未做过其中之一)。
此检查应该有效:
if (s.substring(0, 4) == originalText) {
// update text
}
但考虑考虑 InputFilter,正如评论所建议的那样。
请考虑 OP 评论中的@Gabe Sechan 建议,单独使用 EditText
并不是最佳解决方案。
如果您仍然需要使用 EditText
那么您可以更改条件以检查 EditText
观察者返回的 CharSequence
是否以使用 [=16 的原始文本开头=] 方法
et.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
s?.let {
if (!s.startsWith(originalText)) {
if (s.length <= originalText.length) {
et.setText(originalText)
et.setSelection(originalText.count())
} else {
et.setText(originalText + s.subSequence(originalText.length, s.length))
et.setSelection(s.count())
}
}
}
}
override fun afterTextChanged(s: Editable?) {}
})
您可以使用文本字段,它是 TextInputEditText
和 TextInputLayout
的组合。然后你可以像这样设置一个前缀:
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:prefixText="@string/prefix_text">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
TextInputEditText
获得焦点后,前缀将立即可见。由于它不是 EditText
内容的一部分,因此用户无法修改它。
有用的链接:
我有一个 EditText
,其中包含一些不得删除的预先存在的文本。应该只允许用户在视图中追加文本。
我现在的解决方案如下所示,我检查 EditText
的新长度是否比原始文本短。如果是,则用户试图删除一个字符,所以我只需用原始文本重新填充视图并移动光标。这个解决方案的问题是用户可以输入比原始长度更长的文本,然后将光标的位置更改为原始文本中的某个位置,最后删除字符。
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val originalText = "Hello"
binding.et.setText(originalText)
binding.et.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
s?.let {
if (s.length < originalText.length) {
binding.et.setText(originalText)
binding.et.setSelection(originalText.count())
}
}
}
override fun afterTextChanged(s: Editable?) {}
})
}
我该怎么办?我对所有想法持开放态度。
谢谢!
编辑:
我也试过组合 EditText
和 TextView
(正如一些人所建议的那样)但是布局很难实现,因为原始文本和新文本都可以跨越多行.我上面的解决方案在原文中包含一个单词,但可能有很多。所以我需要迎合这种情况:
...其中白色框代表 TextView
,红色框代表 EditText
。
我认为 Bö macht Blau 的回答也不会奏效,因为前缀在它自己的“列”中。
我想我将不得不使用 Zain 的解决方案 (startsWith()
) 或创建自定义视图(尽管我以前从未做过其中之一)。
此检查应该有效:
if (s.substring(0, 4) == originalText) {
// update text
}
但考虑考虑 InputFilter,正如评论所建议的那样。
请考虑 OP 评论中的@Gabe Sechan 建议,单独使用 EditText
并不是最佳解决方案。
如果您仍然需要使用 EditText
那么您可以更改条件以检查 EditText
观察者返回的 CharSequence
是否以使用 [=16 的原始文本开头=] 方法
et.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
s?.let {
if (!s.startsWith(originalText)) {
if (s.length <= originalText.length) {
et.setText(originalText)
et.setSelection(originalText.count())
} else {
et.setText(originalText + s.subSequence(originalText.length, s.length))
et.setSelection(s.count())
}
}
}
}
override fun afterTextChanged(s: Editable?) {}
})
您可以使用文本字段,它是 TextInputEditText
和 TextInputLayout
的组合。然后你可以像这样设置一个前缀:
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:prefixText="@string/prefix_text">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.google.android.material.textfield.TextInputLayout>
TextInputEditText
获得焦点后,前缀将立即可见。由于它不是 EditText
内容的一部分,因此用户无法修改它。
有用的链接: