Диалог

Компонент Dialog отображает диалоговые сообщения или запрашивает ввод данных пользователем на слое над основным содержимым приложения. Он создает прерывающий пользовательский интерфейс для привлечения внимания пользователя.

Среди вариантов использования диалога можно выделить следующие:

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

Диалоговое окно оповещения

Компонуемый AlertDialog предоставляет удобный API для создания диалога в стиле Material Design. AlertDialog имеет определенные параметры для обработки определенных элементов диалога. Среди них следующие:

  • title : текст, отображаемый в верхней части диалогового окна.
  • text : Текст, который отображается по центру диалогового окна.
  • icon : Графический элемент, отображаемый в верхней части диалогового окна.
  • onDismissRequest : Функция вызывается, когда пользователь закрывает диалоговое окно, например, нажав за его пределами.
  • dismissButton : Компонуемый элемент, служащий кнопкой «Отклонить».
  • confirmButton : компонуемый элемент, служащий кнопкой подтверждения.

В следующем примере реализованы две кнопки в диалоговом окне оповещения: одна закрывает диалоговое окно, а другая подтверждает его запрос.

@Composable
fun AlertDialogExample(
    onDismissRequest: () -> Unit,
    onConfirmation: () -> Unit,
    dialogTitle: String,
    dialogText: String,
    icon: ImageVector,
) {
    AlertDialog(
        icon = {
            Icon(icon, contentDescription = "Example Icon")
        },
        title = {
            Text(text = dialogTitle)
        },
        text = {
            Text(text = dialogText)
        },
        onDismissRequest = {
            onDismissRequest()
        },
        confirmButton = {
            TextButton(
                onClick = {
                    onConfirmation()
                }
            ) {
                Text("Confirm")
            }
        },
        dismissButton = {
            TextButton(
                onClick = {
                    onDismissRequest()
                }
            ) {
                Text("Dismiss")
            }
        }
    )
}

Эта реализация подразумевает наличие родительского компонуемого объекта, который передает аргументы дочернему компонуемому объекту следующим образом:

@Composable
fun DialogExamples() {
    // ...
    val openAlertDialog = remember { mutableStateOf(false) }

    // ...
        when {
            // ...
            openAlertDialog.value -> {
                AlertDialogExample(
                    onDismissRequest = { openAlertDialog.value = false },
                    onConfirmation = {
                        openAlertDialog.value = false
                        println("Confirmation registered") // Add logic here to handle confirmation.
                    },
                    dialogTitle = "Alert dialog example",
                    dialogText = "This is an example of an alert dialog with buttons.",
                    icon = Icons.Default.Info
                )
            }
        }
    }
}

Эта реализация выглядит следующим образом:

Открытое диалоговое окно оповещения, в котором есть кнопки закрытия и подтверждения.
Рисунок 2. Диалоговое окно оповещения с кнопками.

Диалог компонуемый

Dialog — это базовый компонуемый элемент, который не предоставляет никаких стилей или предопределенных слотов для контента. Это относительно простой контейнер, который вы должны заполнить контейнером, таким как Card . Ниже приведены некоторые ключевые параметры диалога:

  • onDismissRequest : лямбда-выражение, вызываемое, когда пользователь закрывает диалоговое окно.
  • properties : экземпляр DialogProperties , который предоставляет дополнительные возможности для настройки.

Простой пример

Следующий пример — это базовая реализация компонуемого Dialog . Обратите внимание, что он использует Card в качестве вторичного контейнера. Без Card компонент Text отображался бы один над основным содержимым приложения.

@Composable
fun MinimalDialog(onDismissRequest: () -> Unit) {
    Dialog(onDismissRequest = { onDismissRequest() }) {
        Card(
            modifier = Modifier
                .fillMaxWidth()
                .height(200.dp)
                .padding(16.dp),
            shape = RoundedCornerShape(16.dp),
        ) {
            Text(
                text = "This is a minimal dialog",
                modifier = Modifier
                    .fillMaxSize()
                    .wrapContentSize(Alignment.Center),
                textAlign = TextAlign.Center,
            )
        }
    }
}

Эта реализация выглядит следующим образом. Обратите внимание, что когда диалоговое окно открыто, основное содержимое приложения под ним выглядит затемненным и серым:

Диалоговое окно, не содержащее ничего, кроме метки.
Рисунок 3. Минимальный диалог.

Расширенный пример

Ниже приведена более продвинутая реализация компонуемого Dialog . В этом случае компонент вручную реализует интерфейс, аналогичный примеру AlertDialog выше.

@Composable
fun DialogWithImage(
    onDismissRequest: () -> Unit,
    onConfirmation: () -> Unit,
    painter: Painter,
    imageDescription: String,
) {
    Dialog(onDismissRequest = { onDismissRequest() }) {
        // Draw a rectangle shape with rounded corners inside the dialog
        Card(
            modifier = Modifier
                .fillMaxWidth()
                .height(375.dp)
                .padding(16.dp),
            shape = RoundedCornerShape(16.dp),
        ) {
            Column(
                modifier = Modifier
                    .fillMaxSize(),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally,
            ) {
                Image(
                    painter = painter,
                    contentDescription = imageDescription,
                    contentScale = ContentScale.Fit,
                    modifier = Modifier
                        .height(160.dp)
                )
                Text(
                    text = "This is a dialog with buttons and an image.",
                    modifier = Modifier.padding(16.dp),
                )
                Row(
                    modifier = Modifier
                        .fillMaxWidth(),
                    horizontalArrangement = Arrangement.Center,
                ) {
                    TextButton(
                        onClick = { onDismissRequest() },
                        modifier = Modifier.padding(8.dp),
                    ) {
                        Text("Dismiss")
                    }
                    TextButton(
                        onClick = { onConfirmation() },
                        modifier = Modifier.padding(8.dp),
                    ) {
                        Text("Confirm")
                    }
                }
            }
        }
    }
}

Эта реализация выглядит следующим образом:

Диалог с фотографией горы Фезертоп, Виктория. Под изображением находятся кнопка «Отклонить» и кнопка «Подтвердить».
Рисунок 4. Диалоговое окно, содержащее изображение.

Дополнительные ресурсы