Диалог

Компонент 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. Диалоговое окно с изображением.

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