Поле ввода текста встречается в каждом втором приложении: логин, поиск, комментарий. Но иногда нужно не просто прочитать то, что ввёл пользователь, а мгновенно реагировать на каждое нажатие клавиши. В Android Studio для этого существует специальный интерфейс — TextWatcher. На этом занятии мы напишем небольшой проект на Kotlin и разберёмся, как с его помощью следить за вводом, подсчитывать символы и управлять видимостью кнопки. Материал рассчитан на начинающих и поможет сделать интерфейс более отзывчивым.
Что умеет TextWatcher
TextWatcher — это слушатель, который прикрепляется к EditText и получает три события. beforeTextChanged вызывается до того, как текст изменится, и позволяет узнать старый контент. onTextChanged срабатывает прямо в момент изменения — здесь удобно реагировать на новые символы. afterTextChanged выполняется после завершения изменений, когда текст уже обновлён. Для большинства задач достаточно именно последнего метода: можно проверить длину строки, отфильтровать нежелательные символы или изменить состояние других View.
Разметка экрана для примера
Создайте простой LinearLayout с EditText, TextView для отображения количества введённых символов и кнопкой, которая будет активна только при непустом поле.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="24dp">
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Введите текст" />
<TextView
android:id="@+id/tvCounter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginTop="8dp" />
<Button
android:id="@+id/btnSubmit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Отправить"
android:layout_marginTop="16dp"
android:enabled="false" />
</LinearLayout>
Подключаем TextWatcher в Activity
В MainActivity.kt получим ссылки на элементы и добавим слушатель к EditText. В методе afterTextChanged будем обновлять счётчик символов и включать или отключать кнопку.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val editText = findViewById<EditText>(R.id.editText)
val tvCounter = findViewById<TextView>(R.id.tvCounter)
val btnSubmit = findViewById<Button>(R.id.btnSubmit)
editText.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
// не используется
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
// не используется
}
override fun afterTextChanged(s: Editable?) {
val length = s?.length ?: 0
tvCounter.text = "Символов: $length"
btnSubmit.isEnabled = length > 0
}
})
}
}
Упрощённая версия с лямбдой
TextWatcher имеет три метода, но Kotlin позволяет обойтись без написания громоздкого анонимного класса. Можно создать расширение, которое преобразует лямбду в TextWatcher, или использовать готовый doOnTextChanged из AndroidX core-ktx. Добавим зависимость и используем краткий синтаксис.
dependencies {
implementation("androidx.core:core-ktx:1.12.0")
}
Теперь код сокращается до пары строк:
editText.doOnTextChanged { text, _, _, _ ->
val length = text?.length ?: 0
tvCounter.text = "Символов: $length"
btnSubmit.isEnabled = length > 0
}
Фильтрация ввода: запрещаем пробелы
Иногда нужно ограничить допустимые символы. Например, не разрешать вводить пробелы в поле логина. Это делается в методе beforeTextChanged или с помощью InputFilter, но проще всего добавить проверку в afterTextChanged и удалить лишние символы.
override fun afterTextChanged(s: Editable?) {
s?.let {
if (it.contains(" ")) {
val filtered = it.toString().replace(" ", "")
editText.setText(filtered)
editText.setSelection(filtered.length) // курсор в конец
}
}
}
Практические советы
- Не делайте сложных операций в TextWatcher. Он вызывается при каждом изменении, поэтому долгие вычисления или запросы к серверу здесь неуместны. Для этого используйте debounce с корутинами.
- Избегайте рекурсивных вызовов. Если внутри
afterTextChangedвы меняете текст, это снова вызовет TextWatcher. Устанавливайте флаг-защиту или временно отключайте слушатель. - Используйте InputFilter для масок и ограничений. TextWatcher хорош для реакции на текст, но для жёсткого контроля ввода (например, только цифры) лучше подходит
InputFilter.
Коротко о главном
Этот урок в среде Android Studio на языке Kotlin познакомил вас с TextWatcher — удобным инструментом для отслеживания ввода. Вы научились прикреплять его к EditText, обновлять счётчик символов и управлять доступностью кнопки. Теперь ваши поля ввода могут реагировать на каждое действие пользователя. Попробуйте добавить проверку минимальной длины пароля или форматирование номера телефона по мере набора — это закрепит навык.