检测 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 的内容是由用户更改还是以编程方式更改?的主要内容,如果未能解决你的问题,请参考以下文章

按下后退时,EditText不会触发更改

检测用户何时将数据输入edittext立即显示答案[关闭]

Android如何检测“删除”按钮按键盘上删除单个字符?

检查文件是由进程创建还是由用户使用C ++创建

如何检测键盘上的用户活动

EditText - 如何检测输入 3 个或更多字符并执行搜索