检测EditText的内容是由用户还是以编程方式更改的?

时间:2014-02-23 20:12:34

标签: android listview android-edittext textwatcher

我需要一种方法来检测EditText是否已被用户输入内容或应用程序以编程方式更改文本而更改。这样做的任何标准方式?我想我总是可以做一些hackish,比如在setText()之前取消TextWatcher并在之后重新设置它,但是必须有一个更好的方法来做到这一点......对吗?

我尝试检查EditText是否在TextWatcher中聚焦,但是由于EditTexts在滚动时无论如何都“半随机”聚焦,因此没有什么帮助......

背景

我在每个listitem都有一个带有EditTexts的ListView。我已经整理出了存储EditTexts值的基本问题,以便在用户滚动时重用。

我还有一个TextWatcher,用于汇总所有EditTexts中的值,并在用户编辑任何EditTexts的内容时显示总和。

问题是,当我滚动列表并且我的自定义适配器重新输入bindView()上的EditTexts中的存储值时,这也会触发TextWatchers afterTextChanged()方法,导致滚动延迟因为总结功能被触发了。

5 个答案:

答案 0 :(得分:46)

很久以前就已经解决了这个问题,但对于那些在这里寻找答案的人来说,这就是我所做的:

在我即将以编程方式更改它,更改值,然后将Tag重置为null之前,我最终将EditText的Tag设置为某个任意值。然后在我的TextWatcher.afterTextChanged()方法中,我检查Tag是否为null,以确定它是用户还是更改了值的程序。像魅力一样工作!

这样的事情:

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
}

答案 1 :(得分:7)

接受的答案完全有效,但我有另一种方法;

@Override
public void onTextChanged(CharSequence charSequence, 
                         int start, int before, int count) {
    boolean userChange = Math.abs(count - before) == 1; 
    if (userChange) { 

    }
}

通过检查更改是否是单个字符来工作。 这不是一个万无一失的解决方案,因为可能会错过复制粘贴操作,并且也会错过单个字符的非用户更改。 根据您的使用情况,这可能是一个可行的解决方案。

答案 2 :(得分:1)

对我有帮助的一件事是拥有boolean canListenInput字段。在观察者中使用它。

    email.addTextChangedListener(new TextWatcher() {
        @Override
        public void afterTextChanged(Editable s) {
            if (canListenInput) {
                emailChanged = true;
            }
        }
    });

在以编程方式更改文本之前清除它。将其设置在onAttachedToWindow中,(在状态之后)恢复:

@Override
public void onAttachedToWindow() {
    super.onAttachedToWindow();
    canListenInput = true;
}

答案 3 :(得分:0)

根据您的用例(例如,当用户键入另一个字段时,您正在自动填充此字段),您还可以检查视图是否具有焦点,例如:

<input ...  :value="getTimeSlot1Start(index)" @input="setTimeSlot1Start(index)" />

答案 4 :(得分:-1)

您可以通过添加:

来完成此操作
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);
}