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

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

Я попытался проверить, сфокусирован ли EditText в TextWatcher, но это мало помогло, так как EditTexts фокусируется «полу-случайным образом» в любом случае при прокрутке …

Задний план

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

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

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

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

Я закончил настройку тега EditText на какое-то произвольное значение прямо перед тем, как я собираюсь изменить его программно, и изменив значение, а затем сбросив значение тега до нуля. Затем в моем методе 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) { } } 

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

Одна вещь, которая помогла мне, – иметь поле 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; } 

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

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