SwipeDismissableSceneStrategy

class SwipeDismissableSceneStrategy<T : Any> : SceneStrategy


A SceneStrategy that displays entries within a Wear Material component.

Below API level 36, content of the current entry (the last entry on the backstack) is displayed within a BasicSwipeToDismissBox to detect swipe back gestures.

API level 36 onwards, SwipeDismissableSceneStrategy listens to platform predictive back events for navigation, and BasicSwipeToDismissBox is not used for swipe gesture detection. Also, transition specifications can be overridden at NavEntry level.

Example of a androidx.navigation3.ui.NavDisplay with SwipeDismissableSceneStrategy alternating between list and detail entries:

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.navigation3.runtime.NavKey
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.runtime.rememberNavBackStack
import androidx.navigation3.ui.NavDisplay
import androidx.wear.compose.foundation.lazy.TransformingLazyColumn
import androidx.wear.compose.foundation.lazy.items
import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState
import androidx.wear.compose.material3.Card
import androidx.wear.compose.material3.EdgeButton
import androidx.wear.compose.material3.ListHeader
import androidx.wear.compose.material3.ScreenScaffold
import androidx.wear.compose.material3.SurfaceTransformation
import androidx.wear.compose.material3.Text
import androidx.wear.compose.material3.TitleCard
import androidx.wear.compose.material3.lazy.rememberTransformationSpec
import androidx.wear.compose.material3.lazy.transformedHeight
import androidx.wear.compose.navigation3.rememberSwipeDismissableSceneStrategy

// Example of using a NavDisplay with SwipeDismissableSceneStrategy for list-detail navigation.

// Strongly-typed, serializable navigation destinations are defined at global scope as follows:
// @Serializable object NotificationList : NavKey
// @Serializable data class NotificationDetail(val id: Int) : NavKey

// NotificationItem needs to be defined at top-level or class-level to ensure stability in
// Compose:
// data class NotificationItem(val id: Int, val title: String, val body: String)
val backStack = rememberNavBackStack(NotificationList)

val notifications = remember {
    listOf(
        NotificationItem(
            0,
            "☕ Coffee Break? Grab a pick-me-up",
            "Step away from the screen and grab a pick-me-up. Step away from the screen and grab a pick-me-up.",
        ),
        NotificationItem(
            1,
            "🌟 You're Awesome!",
            "Just a little reminder in case you forgot 😊",
        ),
        NotificationItem(
            2,
            "👀 Did you know our latest feature?",
            "Check out [app name]'s latest feature update.",
        ),
        NotificationItem(
            3,
            "📅 Appointment Time In 15 Minutes",
            "Your meeting with [name] is in 15 minutes.",
        ),
    )
}

NavDisplay(
    backStack = backStack,
    sceneStrategy = rememberSwipeDismissableSceneStrategy(),
    entryProvider =
        entryProvider {
            entry<NotificationList> {
                val state = rememberTransformingLazyColumnState()
                val transformationSpec = rememberTransformationSpec()
                ScreenScaffold(
                    state,
                    edgeButton = { EdgeButton(onClick = onExit) { Text("Exit") } },
                ) { contentPadding ->
                    TransformingLazyColumn(state = state, contentPadding = contentPadding) {
                        item {
                            ListHeader(
                                transformation = SurfaceTransformation(transformationSpec),
                                modifier =
                                    Modifier.transformedHeight(this, transformationSpec)
                                        .animateItem(),
                            ) {
                                Text("Notifications")
                            }
                        }
                        items(notifications) { notification ->
                            Card(
                                onClick = {
                                    backStack.add(NotificationDetail(notification.id))
                                },
                                transformation = SurfaceTransformation(transformationSpec),
                                modifier =
                                    Modifier.fillMaxWidth()
                                        .transformedHeight(this, transformationSpec)
                                        .animateItem(),
                            ) {
                                Text(notification.title)
                            }
                        }
                    }
                }
            }

            entry<NotificationDetail> { key ->
                val item = requireNotNull(notifications.find { item -> item.id == key.id })
                ScreenScaffold { contentPadding ->
                    Box(
                        Modifier.fillMaxSize().padding(contentPadding),
                        contentAlignment = Alignment.Center,
                    ) {
                        TitleCard(title = { Text(item.title) }, content = { Text(item.body) })
                    }
                }
            }
        },
)
Parameters
<T : Any>

the KType of the backstack key

Summary

Public constructors

<T : Any> SwipeDismissableSceneStrategy(
    state: SwipeDismissableSceneStrategyState,
    modifier: Modifier,
    isUserSwipeEnabled: Boolean
)

Public functions

open Scene<T>?

Public properties

Boolean

Boolean Whether swipe-to-dismiss gesture is enabled.

Modifier

The modifier to be applied to the layout

SwipeDismissableSceneStrategyState

State containing information about ongoing swipe and animation.

Inherited functions

From androidx.navigation3.scene.SceneStrategy
open infix SceneStrategy<T>
then(sceneStrategy: SceneStrategy<T>)

Public constructors

SwipeDismissableSceneStrategy

<T : Any> SwipeDismissableSceneStrategy(
    state: SwipeDismissableSceneStrategyState,
    modifier: Modifier = Modifier,
    isUserSwipeEnabled: Boolean = true
)
Parameters
<T : Any>

the KType of the backstack key

state: SwipeDismissableSceneStrategyState

State containing information about ongoing swipe and animation. This parameter is unused API level 36 onwards, because the platform supports predictive back and SwipeDismissableSceneStrategy uses platform gestures to detect the back gestures.

modifier: Modifier = Modifier

The modifier to be applied to the layout

isUserSwipeEnabled: Boolean = true

Boolean Whether swipe-to-dismiss gesture is enabled.

Public functions

open fun SceneStrategyScope<T>.calculateScene(entries: List<NavEntry<T>>): Scene<T>?

Public properties

isUserSwipeEnabled

Added in 1.6.0-alpha08
val isUserSwipeEnabledBoolean

Boolean Whether swipe-to-dismiss gesture is enabled.

modifier

Added in 1.6.0-alpha08
val modifierModifier

The modifier to be applied to the layout

state

Added in 1.6.0-alpha08
val stateSwipeDismissableSceneStrategyState

State containing information about ongoing swipe and animation. This parameter is unused API level 36 onwards, because the platform supports predictive back and SwipeDismissableSceneStrategy uses platform gestures to detect the back gestures.