EditText: различать изменение текста с помощью setText () или ввода с клавиатуры - PullRequest
16 голосов
/ 15 июня 2011

У меня есть EditText Просмотр, который редактируется с помощью setText() из моего кода и пользователем с помощью (мягкой / жесткой) клавиатуры и - если возможно, с помощью речевого ввода.Я хочу обрабатывать ввод, сделанный моим кодом, не так, как обычный пользовательский ввод: если происходит пользовательский ввод, должно быть запущено внутреннее событие.Но я не знаю, как провести различие между ними.Ранее - при разработке на эмуляторе - я использовал метод onKeyDown(), чтобы поймать пользовательский ввод.Однако при тестировании на реальном устройстве я обнаружил, что onKeyDown() не вызывается с клавиатуры.Кроме того, ввод речи не будет распознаваться, хотя я считаю, что это незначительный недостаток.Так что это решение для меня не вариант.

С другой стороны, есть метод onTextChanged(), но он вызывается как setText(), так и вводом с клавиатуры.Итак, как я могу различить оба или какой метод вызывается только пользовательским вводом, но не при использовании setText(), поэтому я могу перезаписать его?

Ответы [ 5 ]

5 голосов
/ 15 июля 2011

Я наконец-то решил проблему, реализовав InputConnectionWrapper (см. этот вопрос и, в частности, ответ для примера реализации), в котором есть различные способы получения ввода с программной клавиатуры. Я возвращаю InputConnectionWrapper по методу EditText.onCreateInputConnection(). Для жестких клавиатур я использую EditText.onPreIme(). Все эти методы перезаписываются и направляют их ввод через мою структуру, которая обрабатывает ввод текста и обновляет представление соответствующим образом. Это означает, что во всех этих перезаписанных методах (кроме onCreateInputConnection()) метод super называется , а не , потому что я сам обновляю View. Это предотвращает несоответствия между моей моделью данных и представлением.

4 голосов
/ 15 июня 2011

Я считаю, что Android не позволяет различать программно и вручную введенный текст. Единственный обходной путь для вас - использовать некоторые sla, которые будут указывать, когда тест был установлен вашим кодом, потому что вы всегда знаете, когда вызываете setText ().

2 голосов
/ 30 июня 2014

Вы можете использовать флаг для дифференциации.

((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;
}
0 голосов
/ 15 марта 2019

Здесь уже есть много хороших обходных путей! Я хотел добавить то, что мне помогло, чтобы дать варианты тому, у кого может возникнуть эта проблема в будущем.

Я использовал TextWatcher и просто полагался на проверку того, какой элемент в данный момент имеет фокус, когда редактируется EditText. Обратите внимание, что это будет работать, если в вашем приложении пользователь должен фокусироваться на EditText (например, щелкая по нему) перед вводом текста, и вы уверены, что другой элемент будет иметь фокус при использовании setText в вашем коде.

Как то так

yourEditText.addTextChangedListener(
            new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    if (yourEditText.hasFocus) {
                        //this is a user input
                    }
                }

                @Override
                public void afterTextChanged(Editable s) {

                }
            }
    );
0 голосов
/ 03 апреля 2017

У меня была эта проблема при вращении устройства.Мой 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
            }
        }
    }
);
...