Определить, было ли содержимое EditText изменено пользователем или программно?

мне нужен способ определить, был ли EditText изменен пользователем, набрав что-то или приложением, изменившим текст программно. Любой стандартный способ сделать это? Думаю, я всегда мог сделать что-то хакерское, например, расстроить TextWatcher перед setText() и потом снова установить его, но должен быть лучший способ сделать это... правильно?

Я попытался проверить, сосредоточен ли EditText в TextWatcher, но это мало помогло, так как EditTexts фокусируется "полуслучайно" в любом случае при прокрутке...

фон

у меня есть ListView с EditTexts в каждом listitem. Я разобрался с основной проблемой хранения значений для EditTexts для повторного использования при прокрутке пользователя.

у меня также есть TextWatcher, который суммирует значения во всех EditTexts и отображает сумму, когда пользователь редактирует содержимое любого из EditTexts.

проблема это когда я прокручиваю список, и мой пользовательский адаптер повторно вводит сохраненные значения в EditTexts on bindView(), что также вызывает TextWatchers afterTextChanged() метод, вызывающий задержку прокрутки, потому что запускается функция суммирования.

4 ответов


это разобралось давно, но для тех, кто находит свой путь сюда в поисках ответа, вот что я сделал:

Я закончил установку тега EditText на некоторое произвольное значение прямо перед тем, как я собираюсь изменить его программно и изменить значение, а затем сбросить тег на null. Затем в моем TextWatcher.метод afterTextChanged () я проверяю, является ли тег нулевым или нет, чтобы определить, был ли это пользователь или программа, которая изменила значение. Работает как очарование!

что-то вроде этого:

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
}

принятый ответ совершенно действителен, но у меня есть другой подход;

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

    }
}

он работает, проверяя, было ли изменение одним символом. Это не является надежным решением, поскольку операции копирования и вставки могут быть пропущены,а также изменения одного символа, не являющиеся пользовательскими. В зависимости от вашего использования, это может быть жизнеспособным решением.


одна вещь, которая помогла мне, - это логическое поле canListenInput. Используйте его внутри watcher.

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

очистите его перед программным изменением текста. Установите его внутри onAttachedToWindow, (после восстановления состояния):

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

вы можете сделать это, добавив:

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);
}