Для работы с элементов EditText
когда-нибудь вам придётся организовывать слежение за вводов пользователя. Есть стандартный OnKeyListener
, но он как-то странно работает 0_о. Но обо всём попорядку.
OnKeyListener
Можно на EditText
повесить OnKeyListener
, который будет отслеживать нажатия на виртуальной клавиатуре. Как-то так:
((EditText)findViewById(R.id.resultNumericSystemTE)). setOnKeyListener(new View.OnKeyListener(){ public boolean onKey(View v, int keyCode, KeyEvent event){ return false; } } );
Вроде всё нормально, в keyCode
у нас ID нажатой клавиши. По сути всё, можем принимать нажатую кнопку или отменять ввод. Вот только это событие прокает почему-то лишь на кнопки по манипулированию: удаление символа, Enter и т.д.
TextWatcher
Ок, ищем другое решение. Находим интересный класс TextWatcher
. Пробуем повесить на наш EditText:
TextWatcher inputTW = new TextWatcher() { public void afterTextChanged(Editable s) { } public void beforeTextChanged(CharSequence s, int start, int count, int after){ } public void onTextChanged(CharSequence s, int start, int before, int count) { } }; ((EditText)findViewById(R.id.MyTE)).addTextChangedListener(inputTW);
Супер! Теперь можно что-то сделать с EditText до и после нажатия. Вот только есть одна проблемка — нету ссылки на сам EditText
внутри TextWatcher
. Можно конечно обращаться внутри обработчика глобально, типо:
public void afterTextChanged(Editable s) { EditText et = (EditText)findViewById(R.id.MyTE); }
Да, будет всё отлично работать, но тогда при написании обработчиков на все EditText
придётся дублировать кучу кода. А хотелось бы где-то прописать один раз этот, так сказать, шаблон поведения, а потом юзать его.
Свой TextWatcher
И да, можно *__* В Java есть implements — это дополнение к определению класса, реализующего некоторый интерфейс(ы). Создаём свой класс. Как пример, хотим, чтобы в EditText
юзер не мог ввести больше 2 символов:
public class TextWatcherP implements TextWatcher { public EditText editText; public TextWatcherP(EditText et){ super(); editText = et; } public void afterTextChanged(Editable s) { if(editText.getText().length() == 3){ editText.setText(editText.getText().subSequence(0, editText.getText().length()-1)); } } public void beforeTextChanged(CharSequence s, int start, int count, int after){ } public void onTextChanged(CharSequence s, int start, int before, int count) { } }
По сравнению с базовым классом, наш в конструкторе принимает ссылку на EditText
, что устраняет проблему описанную выше. Использовать же просто:
EditText et = (EditText)findViewById(R.id.MyTE) TextWatcherP inputTextWatcher= new TextWatcherP(et); et.addTextChangedListener(inputTextWatcher);
Уведомление: Android: программное отключение автокоррекции в EditText | Suvitruf's Blog
Полезная статья, сам использовал данный класс при написании одного приложения.
Также хотел применить его для реализации маски ввода в edittext, чтобы текст вводился таким образом: «123», далее «1 234», далее «12 345», далее «123 456» и т.д. Так и не смог этого сделать. Несмотря на то, что в логкат выводилось так как мне нужно, в edittext попадало без разрывов между разрядами. Может как-нибудь добью эту проблему.
Спасибо огромное, именно это и искал TextWatcher то что нужно.
ОГРОМНОЕ спасибо, наконец то дошло, как сделать то что я хочу.
Чтоб не писать свой класс можно объявить EditText с final :
final EditText et = (EditText)findViewById(R.id.MyTE)
Тогда уже в TextWatcher можно будет к et прямо обращаться.
А если я хочу один обработчик для многих EditText, как в этом случае определять какой именно EditText инициировал вызов метода?
К примеру, сделать свой класс, унаследовав его от
TextWatcher
.