Как обновить один и тот же EditText с помощью TextWatcher?

В моем приложении Android мне нужно реализовать интерфейс TextWatcher для реализации onTextChanged . Проблема у меня есть, я хочу обновить тот же EditText С помощью некоторой дополнительной строки. Когда я пытаюсь это сделать, программа завершается.

  final EditText ET = (EditText) findViewById(R.id.editText1); ET.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { try { ET.setText("***"+ s.toString()); ET.setSelection(s.length()); } catch(Exception e) { Log.v("State", e.getMessage()); } } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }); 

Моя программа завершается, и даже я пытаюсь поймать исключение, как в моем коде, все равно оно завершается. Кто-нибудь знает, почему это происходит и как я могу это достичь? Благодарю.

Содержимое TextView недействительно в событии onTextChanged .

Вместо этого вам нужно обработать событие afterTextChanged чтобы иметь возможность вносить изменения в текст.

Для более подробного объяснения см.: Android TextWatcher.afterTextChanged vs TextWatcher.onTextChanged


Примечание : Ошибка onTextChanged

Obvioulsy, вы вызываете бесконечный цикл, непрерывно меняя текст на событие afterTextChanged .

Из ссылки :

Public abstract void afterTextChanged (Редактируемые)
Этот метод вызван, чтобы уведомить вас, что где-то в s текст был изменен. Допустимо делать дальнейшие изменения s в этом обратном вызове, но будьте осторожны, чтобы не попасть в бесконечный цикл, потому что любые сделанные вами изменения заставят этот метод вызываться снова рекурсивно.

  • Предложение 1 : если вы можете, проверьте, является ли s уже тем, что вы хотите, когда событие запускается.

     @Override public void afterTextChanged(Editable s) { if( !s.equalsIngoreCase("smth defined previously")) s = "smth defined previously"; } 
  • Предложение 2 : если вам нужно делать более сложные вещи (форматирование, валидация), вы можете использовать synchronized метод, подобный этому сообщению.

Примечание 2 : Форматирование ввода как частично скрытого с n звездами до последних 4 символов (**** четыре)

Вы можете использовать что-то вроде этого в предположении 1 :

  @Override public void afterTextChanged(Editable s) { String sText = ET.getText().toString() if( !isFormatted(sText)) s = format(sText); } bool isFormatted(String s) { //check if s is already formatted } string format(String s) { //format s & return } 

Чтобы дополнить ответ Zortkun (где примерный код довольно сломан), так вы будете использовать afterTextChanged() для обновления одного и того же EditText :

 editText.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) { } @Override public void afterTextChanged(Editable editable) { if (!editable.toString().startsWith("***")) { editable.insert(0, "***"); } } }); 

Ознакомьтесь с интерфейсом Editable чтобы узнать о других операциях, кроме insert() .

Обратите внимание, что легко завершить бесконечный цикл (изменения, которые вы вызываете afterTextChanged() снова), поэтому обычно вы делаете свои изменения внутри условия if , как указано выше.

Как afterTextChanged() javadocs говорят:

Допустимо делать дальнейшие изменения s в этом обратном вызове, но будьте осторожны, чтобы не попасть в бесконечный цикл, потому что любые сделанные вами изменения заставят этот метод вызываться снова рекурсивно.

Поздний ответ, если кто-то смотрит на это, как я это сделал.

  • Сначала установить addTextChangedListener
  • В одном из обратных вызовов (скажем, onTextChanged ()) удалить addTextChangedListener
  • Все еще заинтересованные в получении обновлений, добавьте его снова.

Вот код.

 editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { Log.d("log", "before"); } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { Log.d("log", "after"); editText.removeTextChangedListener(this); ediText.setText("text you wanted to put"); editText.addTextChangedListener(this); } @Override public void afterTextChanged(Editable s) { } });