понедельник, 4 марта 2013 г.

Отслеживание изменений в EditText

Как выяснилось, среди слушателей (Listeners) визуального компонента EditText нет такого крайне востребованного слушателя, как слушатель изменения данных внутри компонента. У него имеются лишь следующие 11 слушателей:

OnClickListener - срабатывает при щелчке по полю ввода.
OnCreateContextMenuListener - срабатывает при построении контекстного меню.
OnDragListener - срабатывает при событиях перетаскивания отпускания.
OnEditorActionListener - срабатывает при нажатии Enter и при других команд редактирования, но не срабатывает на ввод обычных символов.
OnFocusChangeListener - срабатывает при потере или получении фокуса компонентом
OnGenericMotionListener - срабатывает при перемещении мыши над компонентом
OnHoverListener - срабатывает при возникновении события "hover", т.е. когда при наведении мыши изменяется внешний вид компонента.
OnKeyListener - срабатывает при нажатии кнопок аппаратной клавиатуры. При нажатии кнопок программной клавиатуры, как правило, не срабатывает.
OnLongClickListener - срабатывает при длительном удержании нажатия на компоненте
OnSystemUiVisibilityChangeListener - срабатывает при изменении видимости статусной строки в пользовательском интерфейсе системы.
OnTouchListener - срабатывает при касании компонента. При обработке этого события у меня почему-то зависала обработка события OnLongClickListener.

Как видите, среди них нет ничего, что могло бы отследить элементарные изменения текста внутри компонента. Но помимо методов установки слушателей "setOn...", у компонента  EditText есть интересный метод добавления слушателя с названием addTextChangedListener! Почему вместо установки слушателя, как сделано в 11 случаях, используется его добавление (в единственном случае) - мне непонятно.Тем не менее, используем эту возможность.

В качестве слушателя метод предлагает нам установить интерфейсный класс: TextWatcher. Как мы знаем, интерфейсный класс - это класс с пустыми методами, которые заполняются самим программистом. Методов в классе три: beforeTextChanged, onTextChanged и afterTextChanged. При возникновении события изменения текста они автоматически вызываются в определённом порядке. Их названия говорят сами за себя:
 
beforeTextChanged(CharSequence s, int start, int count, int after) - метод вызывается до изменений, чтобы уведомить нас, что в строке s, начиная с позиции start вот-вот будут заменены count символов, новыми after символами. Изменение текста s в этом методе является ошибкой.

onTextChanged(CharSequence s, int start, int before, int count) - метод вызывается, чтобы уведомить нас, что в строке s, начиная с позиции start, только что заменены after символов, новыми count символами. Изменение текста s в этом методе является ошибкой.

afterTextChanged(Editable s) - метод вызывается, чтобы уведомить нас, что где-то в строке s, текст был изменен. В этом методе можно вносить изменения в текст s, но будьте осторожны, чтобы не зациклиться, потому что любые изменения в s рекурсивно вызовут этот же метод.

Итак, пример подключения слушателя изменения текста к компоненту EditText:
editText1.addTextChangedListener(new TextWatcher(){
    @Override
    public void afterTextChanged(Editable s) {
        // Прописываем то, что надо выполнить после изменения текста
    }
    
    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    }
});

17 комментариев:

  1. красава, спасибо

    ОтветитьУдалить
  2. то что искал Спасибо автору работает

    View view = inflater.inflate(R.layout.fragment_var, null);
    editText = (EditText) view.findViewById(R.id.var_edit);
    checkBox = (CheckBox) view.findViewById(R.id.var_check);
    checkBox.setChecked(Boolean.TRUE);



    editText.addTextChangedListener(new TextWatcher(){
    // /**
    // * beforeTextChanged(CharSequence s, int start, int count, int after) - метод вызывается до изменений, чтобы уведомить нас, что в строке s, начиная с позиции start вот-вот будут заменены count символов, новыми after символами. Изменение текста s в этом методе является ошибкой.
    // * onTextChanged(CharSequence s, int start, int before, int count) - метод вызывается, чтобы уведомить нас, что в строке s, начиная с позиции start, только что заменены after символов, новыми count символами. Изменение текста s в этом методе является ошибкой.
    // * afterTextChanged(Editable s) - метод вызывается, чтобы уведомить нас, что где-то в строке s, текст был изменен. В этом методе можно вносить изменения в текст s, но будьте осторожны, чтобы не зациклиться, потому что любые изменения в s рекурсивно вызовут этот же метод.
    // */

    @Override
    public void afterTextChanged(Editable s) {
    // Прописываем то, что надо выполнить после изменения текста
    checkBox.setChecked(Boolean.FALSE);
    if (editText.getText().toString().equals(""))
    {
    // Здесь код, если EditText пуст
    checkBox.setChecked(Boolean.TRUE);
    }
    else
    {
    // если есть текст, то здесь другой код
    checkBox.setChecked(Boolean.FALSE);
    }
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    //Прописываем то, что надо выполнить до изменений
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    //только что заменены
    }
    });

    ОтветитьУдалить
    Ответы
    1. Кто-нибудь подскажет как отключить добавленный таким образом слушатель?

      editText1.addTextChangedListener(new TextWatcher(){
      @Override
      public void afterTextChanged(Editable s) {
      // Прописываем то, что надо выполнить после изменения текста
      }

      @Override
      public void beforeTextChanged(CharSequence s, int start, int count, int after) {
      }

      @Override
      public void onTextChanged(CharSequence s, int start, int before, int count) {
      }
      });

      Удалить
    2. Может быть, editText1.addTextChangedListener(null);

      Удалить
    3. Не совсем.
      Правильно:
      editText1.removeTextChangedListener(watcher); //здесь watcher - добавленный ранее экземпляр TextWatcher

      Удалить
  3. Большое спасибо!!!

    ОтветитьУдалить
  4. Хорошая статья! Эх... Переписали бы вы их справку. :)

    ОтветитьУдалить
  5. Подскажите пожалуйста, как сделать чтобы при изменении значения в EditText на определенное то выполнялось условие? Т.е. у меня в EditText выводится значение температуры из датчика через микроконтроллер Arduino и мне нужно чтобы при достижении минимального порога срабатывало предупреждение, помогите пожалуйста?

    ОтветитьУдалить
    Ответы
    1. Ну при изменении содержимого сравнивайте это значение с нужным, и при выполнении условия, вызывайте предупреждение. Не очень понимаю, в чём проблема.

      Удалить
    2. Проблема в том, что не получается сравнить. Я недавно только начал изучать Android Studio и очень мало понимаю язык Java, не могли бы вы подсказать как мне реализовать данный вопрос?

      Удалить
    3. То есть, вы не знаете, как написать сравнение на Java? Примерно так же, как и в других языках.
      if (s == "Строка для сравнения") { ... }
      Поместите этот код в событие afterTextChanged.
      Вообще, прежде чем лезть в такие дебри, может, стоит изучить операторы и другие азы языка? Кстати, вместо Java рекомендую учить сразу Котлин, на нём исходник компактнее получается.

      Удалить
  6. Подскажите пожалуйста, я начинающий, мне нужно что бы при изменении числа в editText он выводил разницу нового и предыдущего числа в TextView? как это можно реализовать?

    ОтветитьУдалить
  7. Пидарасы задрали спамить

    ОтветитьУдалить