Диалоговые окна — это небольшие всплывающие подсказки, которые просят пользователя подтвердить действие, выбрать вариант или просто сообщают важную информацию. В этом уроке из цикла Android Studio Kotlin уроки мы научимся создавать их без сторонних библиотек, используя встроенный в Android SDK класс AlertDialog. Вы узнаете, как добавить кнопки, обработать нажатие и не потерять данные при повороте экрана.
Зачем нужны диалоги и какими они бывают
Диалог привлекает внимание пользователя и требует немедленного решения: «Да» или «Нет», «ОК» или «Отмена». Их используют для подтверждения удаления, выбора цвета, ввода пароля или просто для показа сообщения об ошибке. В Android есть несколько способов создать диалог, но мы начнём с самого простого и гибкого — AlertDialog.Builder.
Простейший диалог с одной кнопкой
Создайте в вашей Activity метод, который будет показывать диалог. Внутри него настройте Builder: установите заголовок, текст и кнопку «ОК». При нажатии диалог просто закроется.
private fun showSimpleDialog() {
AlertDialog.Builder(this)
.setTitle("Привет!")
.setMessage("Это ваш первый диалог на Kotlin.")
.setPositiveButton("ОК") { dialog, _ ->
dialog.dismiss()
}
.show()
}
Вызовите этот метод, например, при клике на кнопку. На экране появится стандартное окно с текстом и одной кнопкой.
Диалог с двумя кнопками: Да/Отмена
Классический сценарий — подтверждение выхода из приложения. Builder позволяет добавить три типа кнопок: положительную, отрицательную и нейтральную. Добавим две: «Да» и «Отмена».
private fun showExitDialog() {
AlertDialog.Builder(this)
.setTitle("Выход")
.setMessage("Вы действительно хотите выйти?")
.setPositiveButton("Да") { dialog, _ ->
finish() // закрываем Activity
dialog.dismiss()
}
.setNegativeButton("Отмена") { dialog, _ ->
dialog.dismiss()
}
.show()
}
Теперь пользователь случайно не выйдет — диалог переспросит. Логика каждой кнопки задаётся в лямбде.
Диалог со списком: AlertDialog с пунктами
Иногда нужно предложить выбор из нескольких вариантов. Builder умеет показывать список строк. При тапе по элементу диалог закрывается, а вы получаете индекс выбранного пункта.
val colors = listOf("Красный", "Зелёный", "Синий")
private fun showListDialog() {
AlertDialog.Builder(this)
.setTitle("Выберите цвет")
.setItems(colors.toTypedArray()) { dialog, which ->
Toast.makeText(this, "Вы выбрали: ${colors[which]}", Toast.LENGTH_SHORT).show()
dialog.dismiss()
}
.show()
}
Здесь which — индекс элемента в массиве. Никаких адаптеров писать не нужно, всё делает Builder.
Диалог с радиокнопками (radio buttons)
Для единственного выбора с сохранением состояния подходит метод setSingleChoiceItems. Вы передаёте массив строк и индекс текущего выбора, а Builder отобразит кружки для отметки.
val sizes = listOf("Маленькая", "Средняя", "Большая")
private var selectedSize = 0
private fun showSingleChoiceDialog() {
AlertDialog.Builder(this)
.setTitle("Размер пиццы")
.setSingleChoiceItems(sizes.toTypedArray(), selectedSize) { dialog, which ->
selectedSize = which
}
.setPositiveButton("Принять") { dialog, _ ->
Toast.makeText(this, "Выбрано: ${sizes[selectedSize]}", Toast.LENGTH_SHORT).show()
dialog.dismiss()
}
.setNegativeButton("Отмена") { dialog, _ -> dialog.dismiss() }
.show()
}
Обратите внимание: состояние сохраняется в переменной selectedSize. При следующем открытии диалога кружок будет стоять там, где оставил пользователь.
Собственная разметка в диалоге
Если ни один из стандартных стилей не подходит, можно внедрить в диалог свою XML-разметку. Создайте res/layout/dialog_login.xml с двумя EditText (логин и пароль). Затем укажите его через setView:
val dialogView = layoutInflater.inflate(R.layout.dialog_login, null)
AlertDialog.Builder(this)
.setTitle("Вход")
.setView(dialogView)
.setPositiveButton("Войти") { dialog, _ ->
val login = dialogView.findViewById<EditText>(R.id.etLogin).text.toString()
val password = dialogView.findViewById<EditText>(R.id.etPassword).text.toString()
// обработайте логин и пароль
dialog.dismiss()
}
.setNegativeButton("Отмена") { dialog, _ -> dialog.dismiss() }
.show()
Теперь у вас полностью кастомный диалог, который можно наполнить любыми View.
Диалог в Jetpack Compose
Если вы используете Compose, там есть компонент AlertDialog. Выглядит он похоже, но все параметры задаются через Composable-функции:
var showDialog by remember { mutableStateOf(false) }
if (showDialog) {
AlertDialog(
onDismissRequest = { showDialog = false },
title = { Text("Удалить запись?") },
text = { Text("Действие нельзя будет отменить") },
confirmButton = {
TextButton(onClick = { showDialog = false }) {
Text("Удалить")
}
},
dismissButton = {
TextButton(onClick = { showDialog = false }) {
Text("Отмена")
}
}
)
}
Всё остальное — кнопки, списки, кастомная вёрстка — тоже делается через Compose-элементы.
Советы для новичков
- Не злоупотребляйте диалогами. Если показывать их слишком часто, пользователь будет раздражаться.
- Явно указывайте кнопку отмены. У пользователя всегда должна быть возможность отказаться от действия, даже если диалог всплыл случайно.
- Сохраняйте состояние при повороте экрана. Переменные вроде
selectedSizeпотеряются, если не поместить их в ViewModel. - Используйте Material Design. Современные приложения выглядят лучше с MaterialAlertDialogBuilder вместо обычного AlertDialog.
Итоги
Сегодня вы освоили диалоговые окна в рамках Android Studio Kotlin уроки. Мы разобрали AlertDialog с одной и двумя кнопками, списком, радио-кнопками и даже кастомной разметкой. Теперь вы можете дать пользователю возможность подтверждать действия или выбирать настройки, не загромождая основной интерфейс. Добавьте диалог в своё приложение — например, подтверждение выхода или выбор цвета темы — и закрепите навык на практике.