Okno dialogowe

Komponent Dialog wyświetla komunikaty w oknie lub prosi użytkownika o podanie danych na warstwie nad główną treścią aplikacji. Wyświetla interfejs, który przerywa działanie aplikacji, aby przyciągnąć uwagę użytkownika.

Przykłady zastosowania okna:

  • potwierdzanie działania użytkownika, np. usunięcia 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 dialogowe z tekstem i ikonami.
Rysunek 1. Przykład okna dialogowego z tekstem i ikonami.

Okno dialogowe alertu

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

  • title: tekst, który pojawia się u góry okna.
  • text: tekst, który pojawia się na środku okna.
  • icon: grafika wyświetlana u góry okna.
  • onDismissRequest: funkcja wywoływana, gdy użytkownik zamyka okno, np. klikając poza nim.
  • dismissButton: funkcja kompozycyjna, która służy jako przycisk odrzucenia.
  • confirmButton: funkcja kompozycyjna, która służy jako przycisk potwierdzenia.

W poniższym przykładzie w oknie alertu są 2 przyciski: jeden do zamykania okna, a drugi do potwierdzania żądania.

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

Implementacja wygląda tak:

Otwarte okno alertu z przyciskami odrzucenia i potwierdzenia.
Rysunek 2. Okno dialogowe alertu z przyciskami.

Komponent kompozycyjny Dialog

Dialog to podstawowy element kompozycyjny, który nie zapewnia żadnego stylu ani wstępnie zdefiniowanych boksów na treści. Jest to stosunkowo prosty kontener, który należy wypełnić kontenerem takim jak Card. Oto niektóre z kluczowych parametrów okna:

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

Podstawowy przykład

Poniższy przykład pokazuje podstawową implementację funkcji kompozycyjnej Dialog. Zwróć uwagę, że jako kontener dodatkowy używany jest Card. Bez elementu Card komponent Text pojawił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,
            )
        }
    }
}

Implementacja wygląda tak: Pamiętaj, że gdy okno jest otwarte, główna zawartość aplikacji pod nim jest przyciemniona i wyszarzona:

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

Przykład zaawansowany

Poniżej znajdziesz bardziej zaawansowaną implementację funkcji kompozycyjnej Dialog. W tym przypadku komponent ręcznie implementuje interfejs podobny do poprzedniego przykładu 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")
                    }
                }
            }
        }
    }
}

Implementacja wygląda tak:

Okno z widokiem na Mount Feathertop w Wiktorii, z przyciskiem odrzucenia i przyciskiem potwierdzenia.
Rysunek 4. Okno dialogowe zawierające obraz.

Dodatkowe materiały