New Compose Multiplatform components arrived on Composables UICheck it out →

Dialog

[Dialog] displays a full-screen dialog, layered over any other content. It takes a single slot, which is expected to be an opinionated Wear dialog content, such as [Alert] or [Confirmation].

The dialog supports swipe-to-dismiss and reveals the parent content in the background during the swipe gesture.

Last updated:

Installation

dependencies {
   implementation("androidx.wear.compose:compose-material:1.4.0-beta03")
}

Overloads

@Composable
@Deprecated(
    "This overload is provided for backwards compatibility with Compose for Wear OS 1.1." +
        "A newer overload is available which uses ScalingLazyListState from " +
        "wear.compose.foundation.lazy package", level = DeprecationLevel.HIDDEN

@Suppress("DEPRECATION"
fun Dialog(
    showDialog: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    scrollState: androidx.wear.compose.material.ScalingLazyListState? =
        androidx.wear.compose.material.rememberScalingLazyListState(),
    properties: DialogProperties = DialogProperties(),
    content: @Composable () -> Unit,
)

Parameters

namedescription
showDialogControls whether to display the [Dialog]. Set to true initially to trigger an 'intro' animation and display the [Dialog]. Subsequently, setting to false triggers an 'outro' animation, then [Dialog] calls [onDismissRequest] and hides itself.
onDismissRequestExecutes when the user dismisses the dialog. Must remove the dialog from the composition.
modifierModifier to be applied to the dialog.
scrollStateThe scroll state for the dialog so that the scroll position can be displayed.
propertiesTypically platform specific properties to further configure the dialog.
contentSlot for dialog content such as [Alert] or [Confirmation].
@Composable
fun Dialog(
    showDialog: Boolean,
    onDismissRequest: () -> Unit,
    modifier: Modifier = Modifier,
    scrollState: ScalingLazyListState? = rememberScalingLazyListState(),
    properties: DialogProperties = DialogProperties(),
    content: @Composable () -> Unit,
)

Parameters

namedescription
showDialogControls whether to display the [Dialog]. Set to true initially to trigger an 'intro' animation and display the [Dialog]. Subsequently, setting to false triggers an 'outro' animation, then [Dialog] calls [onDismissRequest] and hides itself.
onDismissRequestExecutes when the user dismisses the dialog. Must remove the dialog from the composition.
modifierModifier to be applied to the dialog.
scrollStateThe scroll state for the dialog so that the scroll position can be displayed.
propertiesTypically platform specific properties to further configure the dialog.
contentSlot for dialog content such as [Alert] or [Confirmation].

Code Examples

AlertDialogSample

@Composable
@Sampled
fun AlertDialogSample() {
    Box {
        var showDialog by remember { mutableStateOf(false) }
        Column(
            modifier = Modifier.fillMaxSize().padding(horizontal = 20.dp),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Chip(
                onClick = { showDialog = true },
                label = { Text("Show dialog") },
                colors = ChipDefaults.secondaryChipColors(),
            )
        }
        val scrollState = rememberScalingLazyListState()
        Dialog(
            showDialog = showDialog,
            onDismissRequest = { showDialog = false },
            scrollState = scrollState,
        ) {
            Alert(
                scrollState = scrollState,
                verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.Top),
                contentPadding =
                    PaddingValues(start = 10.dp, end = 10.dp, top = 24.dp, bottom = 52.dp),
                icon = {
                    Icon(
                        painter = painterResource(id = R.drawable.ic_airplanemode_active_24px),
                        contentDescription = "airplane",
                        modifier = Modifier.size(24.dp)
                            .wrapContentSize(align = Alignment.Center),
                    )
                },
                title = { Text(text = "Example Title Text", textAlign = TextAlign.Center) },
                message = {
                    Text(
                        text = "Message content goes here",
                        textAlign = TextAlign.Center,
                        style = MaterialTheme.typography.body2
                    )
                },
            ) {
                item {
                    Chip(
                        label = { Text("Primary") },
                        onClick = { showDialog = false },
                        colors = ChipDefaults.primaryChipColors(),
                    )
                }
                item {
                    Chip(
                        label = { Text("Secondary") },
                        onClick = { showDialog = false },
                        colors = ChipDefaults.secondaryChipColors(),
                    )
                }
            }
        }
    }
}

ConfirmationDialogSample

@Composable
@Sampled
@OptIn(ExperimentalAnimationGraphicsApi::class
fun ConfirmationDialogSample() {
    Box {
        var showDialog by remember { mutableStateOf(false) }
        Column(
            modifier = Modifier.fillMaxSize().padding(horizontal = 25.dp),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Chip(
                onClick = { showDialog = true },
                label = { Text("Show dialog") },
                colors = ChipDefaults.secondaryChipColors(),
            )
        }
        Dialog(showDialog = showDialog, onDismissRequest = { showDialog = false }) {
            val animation =
                AnimatedImageVector.animatedVectorResource(R.drawable.open_on_phone_animation)
            Confirmation(
                onTimeout = { showDialog = false },
                icon = {
                    // Initially, animation is static and shown at the start position (atEnd = false).
                    // Then, we use the EffectAPI to trigger a state change to atEnd = true,
                    // which plays the animation from start to end.
                    var atEnd by remember { mutableStateOf(false) }
                    DisposableEffect(Unit) {
                        atEnd = true
                        onDispose {}
                    }
                    Image(
                        painter = rememberAnimatedVectorPainter(animation, atEnd),
                        contentDescription = "Open on phone",
                        modifier = Modifier.size(48.dp)
                    )
                },
                durationMillis = 3000,
            ) {
                Text(text = "Open on phone", textAlign = TextAlign.Center)
            }
        }
    }
}