Определить, было ли содержимое 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);
}