EditText: различать изменение текста с помощью setText() или ввода с клавиатуры
У меня есть EditText
View, который редактируется setText()
из моего кода и пользователем через (мягкую/твердую) клавиатуру и, если возможно, с помощью речевого ввода. Я хочу обрабатывать ввод, сделанный моим кодом, по-другому, чем обычный пользовательский ввод: при входе пользователя происходит внутреннее событие. Но я не знаю, как отличить их обоих. Раньше - при разработке на эмуляторе я использовал метод onKeyDown()
, чтобы поймать пользовательский ввод. Однако при тестировании на реальном устройстве я узнал, что onKeyDown()
не запускается с мягкого ввода клавиатуры. Кроме того, речевой ввод не был бы признан этим, хотя я считаю, что это незначительный недостаток. Так что решение для меня не вариант.
С другой стороны, существует метод onTextChanged()
, но это срабатывает как с помощью setText()
, так и с клавиатуры. Итак, как я могу различать оба метода, или какой метод вызывается только пользователем, но не при использовании setText()
, поэтому я могу его переписать?
Ответы
Ответ 1
Я, наконец, решил проблему, выполнив InputConnectionWrapper
(см. этот вопрос и, в частности, ответ для примера реализации), который имеет различные методы для получения ввода из мягкая клавиатура. Я возвращаю свой InputConnectionWrapper
в методе EditText.onCreateInputConnection()
. Для жестких клавиатур я использую EditText.onPreIme()
. Все эти методы перезаписываются и направляют их вход через мою структуру, которая обрабатывает ввод текста и соответственно обновляет представление. Это означает, что во всех этих перезаписанных методах (кроме onCreateInputConnection()
) супер-метод не называется, потому что я обновляю View сам. Это предотвращает несоответствие между моей моделью данных и представлением.
Ответ 2
Я считаю, что Android не позволяет различать программно и вручную введенный текст. Единственное обходное решение для вас использовать какую-либо sla, которая будет указывать, когда тест был установлен вашим кодом, потому что вы всегда знаете, когда вызываете setText().
Ответ 3
Вы можете использовать флаг для дифференциации.
((EditText) rootView.findViewById(R.id.editText1)).addTextChangedListener(new TextWatcher() {
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
}
public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
}
public void afterTextChanged(Editable editable) {
update(true);
}
});
private boolean updating = false;
private void update(boolean multiply) {
if(updating){
return;
}
updating = true;
EditText editText1 = (EditText) getView().findViewById(R.id.editText1);
editText1.setText("XXX");
updating = false;
}
Ответ 4
У меня возникала эта проблема при повороте устройства. Мой editText находится внутри диалогового окна. Вот как я это решил:
editText.addTextChangedListener(
new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
String newValue = s.toString();
String oldValue = (String) editText.getTag();
if (newValue.length() > 0) {
editText.setTag(newValue);
}
boolean itReallyChanged = oldValue != null && !newValue.equals(oldValue) && !newValue.isEmpty();
if (itReallyChanged) {
// Pretty sure the user genuinely changed this value,
// not the device rotation
}
}
}
);