Okno dialogowe

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.

Dostępne przypadki użycia dialogu:

  • 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 dialogów w stylu Material Design. AlertDialog ma określone parametry do obsługi poszczególnych elementów dialogu. Oto niektóre z 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: kompozyt 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 kompozycyjnej 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 z ostrzeżeniem i przyciskami.

Okno dialogowe

Dialog to podstawowy komponent, który nie zapewnia żadnego stylizowania ani zdefiniowanych wstępnie sekcji treści. Jest to stosunkowo prosty kontener, który powinieneś wypełnić kontenerem takim jak Card. Oto niektóre z kluczowych 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

Zaawansowany przykład

Poniżej przedstawiamy bardziej zaawansowane wdrożenie komponentu Dialog. W tym przypadku komponent ręcznie implementuje interfejs podobny do tego z AlertDialog przykładu powyżej.

@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 dialogowe ze zdjęciem Mount Feathertop w stanie Wiktoria. Pod obrazem znajdują się przycisk odrzucenia i przycisk potwierdzenia.
Rysunek 4. Okno z obrazem.

Dodatkowe materiały