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 on rozpraszający uwagę interfejs, aby przyciągnąć uwagę użytkownika.

Okno dialogowe może służyć na przykład:

  • potwierdzenie działania użytkownika, na przykład usunięcia pliku;
  • Proszenie o dane wejściowe użytkownika, np. w aplikacji do zarządzania zadaniami.
  • prezentowanie 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

Funkcja kompozycyjna AlertDialog to wygodny interfejs API do tworzenia okna z motywem 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 dialogowego.
  • text: tekst wyświetlany na środku okna dialogowego.
  • icon: grafika wyświetlana u góry okna.
  • onDismissRequest: funkcja jest wywoływana, gdy użytkownik zamknie okno, np. gdy kliknie poza nim.
  • dismissButton: kompozyt służący jako przycisk zamknięcia.
  • confirmButton: element kompozycyjny, który służy 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 okna dialogowego:

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

Przykład podstawowy

Poniższy przykład pokazuje podstawową implementację funkcji kompozycyjnej 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 po otwarciu okna główna zawartość aplikacji pod nim jest przyciemniona i wyszarzona:

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