检测 EditText 的内容是由用户更改还是以编程方式更改?
Posted
技术标签:
【中文标题】检测 EditText 的内容是由用户更改还是以编程方式更改?【英文标题】:Detect if content of EditText was changed by user or programmatically? 【发布时间】:2014-03-25 07:07:37 【问题描述】:我需要一种方法来检测 EditText 是否已因用户键入内容或应用程序以编程方式更改文本而发生更改。有什么标准的方法吗?我想我总是可以做一些骇人听闻的事情,比如在 setText()
之前取消设置 TextWatcher 并在之后再次设置它,但是必须有更好的方法来做到这一点......对吗?
我尝试检查 EditText 是否聚焦在 TextWatcher 中,但这并没有什么帮助,因为 EditText 在滚动时无论如何都会“半随机”聚焦...
背景
我在每个列表项中都有一个带有 EditTexts 的 ListView。我已经解决了存储 EditTexts 的值以便在用户滚动时重用的基本问题。
我还有一个 TextWatcher,它汇总所有 EditText 中的值,并在用户编辑任何 EditText 的内容时显示总和。
问题是,当我滚动列表并且我的自定义适配器在 bindView()
上重新输入 EditTexts 中的存储值时,这也会触发 TextWatchers afterTextChanged()
方法,导致滚动滞后,因为求和- up-function 被触发。
【问题讨论】:
您可以覆盖 OnKeyDown() 并在其中触发一个布尔值,以便您知道用户正在输入文本并在您的 textwatcher 中使用它 @JRowan 是的,我想过放弃 TextWatcher 并改用 onKeyDown(),但根据文档 “软件键盘中的按键通常不会触发此侦听器,尽管有些人可能会选择在某些情况下这样做。不要依赖它来捕捉软件按键。" developer.android.com/reference/android/widget/…, android.view.KeyEvent) @BadCash 你有多少 TextWatcher? 在代码中调整类变量标志时如何设置它,在文本观察器中检查该标志,然后重置它? @pskink 列表视图中的每个项目一个,它们在 newItem() 方法中被实例化。 【参考方案1】:这在很久以前就解决了,但是对于任何在这里寻找答案的人来说,这就是我所做的:
在我即将以编程方式更改它之前,我最终将 EditText 的 Tag 设置为某个任意值,然后更改该值,然后将 Tag 重置为 null。然后在我的 TextWatcher.afterTextChanged() 方法中,我检查 Tag 是否为空,以确定是用户还是程序更改了该值。像魅力一样工作!
类似这样的:
edit.setTag( "arbitrary value" );
edit.setText( "My Text Value" );
edit.setTag(null);
然后
public void afterTextChanged(Editable s)
if( view.getTag() == null )
// Value changed by user
else
// Value changed by program
【讨论】:
为我工作!感谢您提供简单易用的解决方案 这个解决方案很棒。这解决了我们一年多来的挣扎。一个问题是你不应该在协程块内检查editText的标签——一定要在块外设置一个变量,然后在里面检查它。【参考方案2】:接受的答案完全有效,但我有另一种方法;
@Override
public void onTextChanged(CharSequence charSequence,
int start, int before, int count)
boolean userChange = Math.abs(count - before) == 1;
if (userChange)
它通过检查更改是否为单个字符来工作。 这不是一个万无一失的解决方案,因为可能会错过复制粘贴操作,并且也会错过单个字符的非用户更改。 根据您的用例,这可能是一个可行的解决方案。
【讨论】:
最佳解决方案...通俗易懂 那么当用户在EditText
中粘贴一些东西时会发生什么? ;)
那么当用户点击自动推荐的单词时会发生什么?
错误答案。如果使用任何剪切/粘贴或突出显示编辑将产生错误的结果。完全错了。
这是错误的答案,原因如下 1. 用户按照@reVerse 的建议粘贴了一些内容 2. 用户点击了 Aloha 的一些建议 不知道为什么这么多人对此表示赞同 :(【参考方案3】:
对我有帮助的一件事是拥有布尔型 canListenInput 字段。在观察者内部使用它。
email.addTextChangedListener(new TextWatcher()
@Override
public void afterTextChanged(Editable s)
if (canListenInput)
emailChanged = true;
);
在以编程方式更改文本之前清除它。将其设置在 onAttachedToWindow 内,(状态后)恢复:
@Override
public void onAttachedToWindow()
super.onAttachedToWindow();
canListenInput = true;
【讨论】:
【参考方案4】:根据您的用例(例如,当用户键入另一个字段时,您会自动填充此字段),您还可以检查视图是否具有焦点,例如:
textView.doAfterTextChanged
val isValueChangedByUser = textView.hasFocus()
// ...
【讨论】:
【参考方案5】:您可以通过添加:
private String current = "";
@Override
public void onTextChanged(CharSequence s, int start, int before, int count)
if(!s.toString().equals(current))
[your_edittext].removeTextChangedListener(this);
//Format your string here...
current = formatted;
[your_edittext].setText(formatted);
[your_edittext].setSelection(formatted.length());
[your_edittext].addTextChangedListener(this);
【讨论】:
以上是关于检测 EditText 的内容是由用户更改还是以编程方式更改?的主要内容,如果未能解决你的问题,请参考以下文章