Okno dialogowe

Komponent Dialog wyświetla komunikaty okien dialogowych lub prosi o dane wejściowe użytkownika w warstwie nad główną treścią aplikacji. Tworzy on przerywający interfejs, który ma przyciągnąć uwagę użytkownika.

Przykłady zastosowań okna dialogowego:

  • potwierdzanie działania użytkownika, np. podczas usuwania pliku;
  • prośba o dane wejściowe użytkownika, np. w aplikacji z listą zadań;
  • wyświetlanie listy opcji do wyboru przez użytkownika, np. wyboru kraju podczas konfigurowania profilu.
okno z tekstem i ikonami;
Rysunek 1. Przykład okna dialogowego wypełnionego tekstem i ikonami.

Okno dialogowe alertu

Funkcja kompozycyjna AlertDialog udostępnia wygodny interfejs API do tworzenia okna dialogowego z motywem Material Design. AlertDialog ma określone parametry do obsługi poszczególnych elementów okna dialogowego. Oto niektóre z nich:

  • title: tekst, który pojawia się u góry okna dialogowego.
  • text: tekst, który pojawia się na środku okna dialogowego.
  • icon: grafika, która pojawia się u góry okna dialogowego.
  • onDismissRequest: funkcja wywoływana, gdy użytkownik zamyka okno dialogowe, np. przez kliknięcie poza nim.
  • dismissButton: funkcja kompozycyjna, która służy jako przycisk zamykania.
  • confirmButton: funkcja kompozycyjna, która służy jako przycisk potwierdzenia.

Poniższy przykład implementuje 2 przyciski w oknie dialogowym alertu – jeden zamyka okno, a drugi potwierdza żądanie.

@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, że funkcja kompozycyjna nadrzędna przekazuje argumenty do 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 dialogowe alertu z przyciskami.

Funkcja kompozycyjna Dialog

Dialog to podstawowa funkcja kompozycyjna, która nie zapewnia żadnych stylów ani predefiniowanych miejsc na treści. Jest to stosunkowo prosty kontener, który należy wypełnić innym kontenerem, np. Card. Oto niektóre z najważniejszych parametrów okna dialogowego:

  • onDismissRequest: lambda wywoływana, gdy użytkownik zamyka okno dialogowe.
  • properties: instancja DialogProperties, która zapewnia dodatkowy zakres dostosowywania.

Podstawowy przykład

Poniższy przykład to podstawowa implementacja funkcji kompozycyjnej Dialog. Zwróć uwagę, że używa ona Card jako kontenera dodatkowego. Bez Card komponent Text pojawiłby się samodzielnie 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. Zwróć uwagę, że gdy okno dialogowe jest otwarte, główna treść aplikacji pod nim jest przyciemniona i wyszarzona:

Okno dialogowe zawierające tylko etykietę.
Rysunek 3. Minimalne okno dialogowe.

Zaawansowany przykład

Poniżej znajdziesz bardziej zaawansowaną implementację funkcji kompozycyjnej Dialog. W tym przypadku komponent ręcznie implementuje interfejs podobny do interfejsu w przykładzie AlertDialog 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 z zdjęciem góry Feathertop w stanie Wiktoria. Pod obrazem znajdują się przyciski odrzucania i potwierdzania.
Rysunek 4. Okno dialogowe zawierające obraz.

Dodatkowe materiały