Dialog

Komponent Dialog wyświetla okna z wiadomościami lub prośbami o wprowadzenie danych przez użytkownika na warstwie nad główną treścią aplikacji. Tworzy ono przerwanie w interfejsie, aby przyciągnąć uwagę użytkownika.

Do dialogów można m.in. wykorzystywać:

  • potwierdzenie działania użytkownika, na przykład usunięcia pliku;
  • Proszenie o dane wejściowe użytkownika, np. w aplikacji do zarządzania listą zadań.
  • Wyświetlanie listy opcji do wyboru przez użytkownika, np. wybór kraju w konfiguracji profilu.
Okno z tekstem i ikonami.
Rysunek 1. Przykład okna z tekstem i ikonami.

Okno dialogowe alertu

Komponent AlertDialog udostępnia wygodne API do tworzenia okna dialogowego w stylu Material Design. AlertDialog ma określone parametry do obsługi poszczególnych elementów dialogu. Należą do nich:

  • title: tekst, który pojawia się u góry okna dialogowego.
  • text: tekst wyśrodkowany w dialogu.
  • icon: grafika wyświetlana u góry okna.
  • onDismissRequest: funkcja wywoływana, gdy użytkownik zamyka okno, np. przez kliknięcie poza nim.
  • dismissButton: kompozyt służący jako przycisk zamknięcia.
  • confirmButton: komponent służący jako przycisk potwierdzenia.

W tym przykładzie w oknie z ostrzeżeniem są 2 przyciski: jeden do zamykania okna i drugi do potwierdzania prośby.

@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")
            }
        }
    )
}

Ta implementacja zakłada funkcję kompozytową nadrzędną, która przekazuje argumenty funkcji kompozytowej podrzędnej w ten sposób:

@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
                )
            }
        }
    }
}

Ta implementacja wygląda tak:

Otwarte okno alertu z przyciskami odrzucania i potwierdzania.
Rysunek 2. Okno alertu z przyciskami.

Okno dialogowe

Dialog to podstawowy komponent, który nie zapewnia żadnego stylizowania ani wstępnie zdefiniowanych miejsc na treści. Jest to stosunkowo prosty kontener, który powinieneś wypełnić kontenerem takim jak Card. Oto niektóre z najważniejszych parametrów dialogu:

  • onDismissRequest: funkcja lambda wywoływana, gdy użytkownik zamknie okno.
  • properties: instancja DialogProperties, która zapewnia dodatkowe możliwości dostosowywania.

Przykład podstawowy

Ten przykład pokazuje podstawową implementację kompozytu Dialog. Pamiętaj, że jako kontener pomocniczy używa Card. Bez elementu Card element Text wyświetlałby się sam nad główną treścią aplikacji.

@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,
            )
        }
    }
}

Ta implementacja wygląda tak. Pamiętaj, że gdy okno jest otwarte, główna treść aplikacji pod nim jest przyciemniona i wygaszona:

Okno, które nie zawiera nic oprócz etykiety.
Rysunek 3. Minimalny dialog.

Przykład zaawansowany

Poniżej przedstawiamy bardziej zaawansowane wdrożenie komponentu Dialog. W tym przypadku komponent ręcznie implementuje interfejs podobny do pokazanego powyżej w przykładzie 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")
                    }
                }
            }
        }
    }
}

Ta implementacja wygląda tak:

Okno z zdjęciem Mount Feathertop w Victorii. Pod obrazem znajdują się przycisk odrzucenia i przycisk potwierdzenia.
Rysunek 4. Okno z obrazem.

Dodatkowe materiały