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ć te przypadki użycia:

  • potwierdzania działania użytkownika, na przykład podczas usuwania pliku.
  • Wymaganie od użytkownika danych wejściowych, np. w aplikacji z listą zadań.
  • Prezentujemy listę opcji do wyboru przez użytkownika, takich jak wybór kraju konfigurację 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. Parametr AlertDialog zawiera szczegółowe parametry: obsługi określonych elementów okna. Należą do nich:

  • title: tekst, który pojawia się u góry okna.
  • text: tekst wyświetlany na środku okna dialogowego.
  • icon: grafika wyświetlana u góry okna.
  • onDismissRequest: funkcja wywoływana po zamknięciu okna przez użytkownika, np. dotykając go na zewnątrz.
  • 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, że nadrzędna funkcja kompozycyjna przekazuje argumenty do w taki 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 zamykania i potwierdzenia.
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. To dość prosty kontener, zapełnij go 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

Poniższy przykład pokazuje podstawową implementację funkcji kompozycyjnej Dialog. Notatka że jako kontenera dodatkowego 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. Okno Minimalne.

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

Implementacja wygląda tak:

Okno ze zdjęciem góry Feathertop w stanie Victoria. Pod obrazem znajdują się przyciski zamykania i potwierdzenia.
Rysunek 4. Okno z obrazem.

Dodatkowe materiały