Dialog

Komponent Dialog wyświetla wyskakujące okienka lub prosi użytkownika o podanie danych nad główną treścią aplikacji. Tworzy on uciążliwy interfejs, przyciągania uwagi użytkowników.

Do dialogów można m.in. wykorzystywać:

  • potwierdzenie działania użytkownika, na przykład usunięcia pliku;
  • Wymaganie od użytkownika danych wejściowych, np. w aplikacji z listą zadań.
  • Wyświetlanie listy opcji do wyboru przez użytkownika, np. wybór kraju w konfiguracji profilu.
Okno zawierające tekst i ikony.
Rysunek 1. Przykład okna zawierającego tekst i ikony.

Okno dialogowe alertu

Funkcja kompozycyjna AlertDialog zapewnia wygodny interfejs API do tworzenia Okno z motywem Material Design. Parametr AlertDialog zawiera szczegółowe parametry: obsługi określonych 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 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: kompozyt służący jako przycisk potwierdzenia.

Poniższy przykład pokazuje 2 przyciski w oknie alertu. Jeden z nich to przycisk 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 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
                )
            }
        }
    }
}

Implementacja wygląda tak:

Otwarte okno alertu z przyciskami zamykania i potwierdzenia.
Rysunek 2. Okno alertu z przyciskami.

Okno z możliwością tworzenia

Dialog to podstawowa funkcja kompozycyjna, która nie określa żadnego stylu ani wstępnie zdefiniowane boksy na treści. To dość prosty kontener, powinien zostać wypełniony kontenerem, takim jak Card. Oto niektóre z nich: kluczowe parametry okna dialogowego:

  • onDismissRequest: funkcja lambda wywoływana, gdy użytkownik zamknie okno.
  • properties: instancja DialogProperties, która udostępnia pewne dodatkowego zakresu personalizacji.

Przykład podstawowy

Poniższy przykład pokazuje podstawową implementację funkcji kompozycyjnej Dialog. Pamiętaj, że jako kontener pomocniczy używa Card. Bez Card Text byłby wyświetlany samodzielnie nad główną zawartoś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 spodem jest zaciemniona i wyszarzona:

Okno, które nie zawiera nic poza etykietą.
Rysunek 3. Okno Minimalne.

Przykład zaawansowany

Poniżej przedstawiliśmy bardziej zaawansowaną implementację funkcji kompozycyjnej Dialog. W tym w takim przypadku komponent ręcznie implementuje interfejs podobny do interfejsu 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")
                    }
                }
            }
        }
    }
}

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