【问题标题】:Detect if content of EditText was changed by user or programmatically?检测 EditText 的内容是由用户更改还是以编程方式更改?
【发布时间】: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() 方法中被实例化。

标签: android listview android-edittext textwatcher


【解决方案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);
      }
      

      【讨论】:

        猜你喜欢
        • 2023-02-22
        • 2013-10-30
        • 2012-02-26
        • 1970-01-01
        • 1970-01-01
        • 2023-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多