SwipeDismissableNavHost

Functions summary

Unit
@Composable
SwipeDismissableNavHost(
    navController: NavHostController,
    graph: NavGraph,
    modifier: Modifier,
    userSwipeEnabled: Boolean,
    state: SwipeDismissableNavHostState
)

Provides a place in the Compose hierarchy for self-contained navigation to occur, with backwards navigation provided by a swipe gesture.

Unit
@Composable
SwipeDismissableNavHost(
    navController: NavHostController,
    startDestination: String,
    modifier: Modifier,
    userSwipeEnabled: Boolean,
    state: SwipeDismissableNavHostState,
    route: String?,
    builder: NavGraphBuilder.() -> Unit
)

Provides a place in the Compose hierarchy for self-contained navigation to occur, with backwards navigation provided by a swipe gesture.

Functions

SwipeDismissableNavHost

@Composable
fun SwipeDismissableNavHost(
    navController: NavHostController,
    graph: NavGraph,
    modifier: Modifier = Modifier,
    userSwipeEnabled: Boolean = true,
    state: SwipeDismissableNavHostState = rememberSwipeDismissableNavHostState()
): Unit

Provides a place in the Compose hierarchy for self-contained navigation to occur, with backwards navigation provided by a swipe gesture.

Once this is called, any Composable within the given NavGraphBuilder can be navigated to from the provided navController.

The builder passed into this method is remembered. This means that for this NavHost, the contents of the builder cannot be changed.

During a swipe-to-dismiss gesture, the previous navigation level (if any) is shown in the background. BackgroundScrimColor and ContentScrimColor of it are taken from LocalSwipeToDismissBackgroundScrimColor and LocalSwipeToDismissContentScrimColor.

Below API level 36, content of the current navigation level is displayed within a BasicSwipeToDismissBox to detect swipe back gestures.

API level 36 onwards, SwipeDismissableNavHost listens to platform predictive back events for navigation, and BasicSwipeToDismissBox is not used for swipe gesture detection. Therefore, Modifier.edgeSwipeToDismiss is not compatible with SwipeDismissableNavHost for API level 36 onwards.

Example of a SwipeDismissableNavHost alternating between 2 screens:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.wear.compose.material.Button
import androidx.wear.compose.material.Text
import androidx.wear.compose.navigation.SwipeDismissableNavHost
import androidx.wear.compose.navigation.composable
import androidx.wear.compose.navigation.rememberSwipeDismissableNavController

// Example of using a NavHost where each destination in the NavGraph has a unique name.
val navController = rememberSwipeDismissableNavController()
SwipeDismissableNavHost(navController = navController, startDestination = "off") {
    composable("off") {
        Column(
            modifier = Modifier.fillMaxSize().background(Color.DarkGray),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center,
        ) {
            Button(onClick = { navController.navigate("on") }) { Text("On") }
        }
    }
    composable("on") {
        Column(
            modifier = Modifier.fillMaxSize().background(Color.DarkGray),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center,
        ) {
            Button(onClick = { navController.navigate("off") }) { Text("Off") }
        }
    }
}

Example of a SwipeDismissableNavHost for which a destination has a named argument:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.navigation.NavType
import androidx.navigation.navArgument
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
import androidx.wear.compose.material.CompactChip
import androidx.wear.compose.material.ListHeader
import androidx.wear.compose.material.Text
import androidx.wear.compose.navigation.SwipeDismissableNavHost
import androidx.wear.compose.navigation.composable
import androidx.wear.compose.navigation.rememberSwipeDismissableNavController

// Example of using a NavHost where we pass an argument to a destination in the NavGraph.
val navController = rememberSwipeDismissableNavController()
SwipeDismissableNavHost(navController = navController, startDestination = "list") {
    composable("list") {
        ScalingLazyColumn(
            modifier = Modifier.fillMaxSize().background(Color.DarkGray),
            contentPadding = PaddingValues(horizontal = 8.dp, vertical = 32.dp),
            verticalArrangement = Arrangement.Center,
        ) {
            item { ListHeader { Text("List Screen") } }
            items(5) { index ->
                CompactChip(
                    modifier = Modifier.padding(vertical = 4.dp),
                    onClick = { navController.navigate("detail/$index") },
                    label = {
                        Text(
                            text = "Item $index",
                            textAlign = TextAlign.Center,
                            modifier = Modifier.fillMaxSize(),
                        )
                    },
                )
            }
        }
    }
    composable(
        route = "detail/{Id}",
        arguments = listOf(navArgument("Id") { type = NavType.IntType }),
    ) { backStackEntry ->
        val itemId = backStackEntry.arguments?.getInt("Id") ?: 0
        Column(
            modifier = Modifier.fillMaxSize().background(Color.DarkGray),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center,
        ) {
            ListHeader { Text("Details Screen") }
            Text("Item $itemId")
        }
    }
}
Parameters
navController: NavHostController

NavHostController for this host

graph: NavGraph

Graph for this host

modifier: Modifier = Modifier

Modifier to be applied to the layout

userSwipeEnabled: Boolean = true

Boolean Whether swipe-to-dismiss gesture is enabled.

state: SwipeDismissableNavHostState = rememberSwipeDismissableNavHostState()

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

Throws
IllegalArgumentException

if no WearNavigation.Destination is on the navigation backstack.

SwipeDismissableNavHost

@Composable
fun SwipeDismissableNavHost(
    navController: NavHostController,
    startDestination: String,
    modifier: Modifier = Modifier,
    userSwipeEnabled: Boolean = true,
    state: SwipeDismissableNavHostState = rememberSwipeDismissableNavHostState(),
    route: String? = null,
    builder: NavGraphBuilder.() -> Unit
): Unit

Provides a place in the Compose hierarchy for self-contained navigation to occur, with backwards navigation provided by a swipe gesture.

Once this is called, any Composable within the given NavGraphBuilder can be navigated to from the provided navController.

The builder passed into this method is remembered. This means that for this NavHost, the contents of the builder cannot be changed.

During a swipe-to-dismiss gesture, the previous navigation level (if any) is shown in the background. BackgroundScrimColor and ContentScrimColor of it are taken from LocalSwipeToDismissBackgroundScrimColor and LocalSwipeToDismissContentScrimColor.

Below API level 36, content of the current navigation level is displayed within a BasicSwipeToDismissBox to detect swipe back gestures.

API level 36 onwards, SwipeDismissableNavHost listens to platform predictive back events for navigation, and BasicSwipeToDismissBox is not used for swipe gesture detection.

Example of a SwipeDismissableNavHost alternating between 2 screens:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.wear.compose.material.Button
import androidx.wear.compose.material.Text
import androidx.wear.compose.navigation.SwipeDismissableNavHost
import androidx.wear.compose.navigation.composable
import androidx.wear.compose.navigation.rememberSwipeDismissableNavController

// Example of using a NavHost where each destination in the NavGraph has a unique name.
val navController = rememberSwipeDismissableNavController()
SwipeDismissableNavHost(navController = navController, startDestination = "off") {
    composable("off") {
        Column(
            modifier = Modifier.fillMaxSize().background(Color.DarkGray),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center,
        ) {
            Button(onClick = { navController.navigate("on") }) { Text("On") }
        }
    }
    composable("on") {
        Column(
            modifier = Modifier.fillMaxSize().background(Color.DarkGray),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center,
        ) {
            Button(onClick = { navController.navigate("off") }) { Text("Off") }
        }
    }
}

Example of a SwipeDismissableNavHost for which a destination has a named argument:

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.navigation.NavType
import androidx.navigation.navArgument
import androidx.wear.compose.foundation.lazy.ScalingLazyColumn
import androidx.wear.compose.material.CompactChip
import androidx.wear.compose.material.ListHeader
import androidx.wear.compose.material.Text
import androidx.wear.compose.navigation.SwipeDismissableNavHost
import androidx.wear.compose.navigation.composable
import androidx.wear.compose.navigation.rememberSwipeDismissableNavController

// Example of using a NavHost where we pass an argument to a destination in the NavGraph.
val navController = rememberSwipeDismissableNavController()
SwipeDismissableNavHost(navController = navController, startDestination = "list") {
    composable("list") {
        ScalingLazyColumn(
            modifier = Modifier.fillMaxSize().background(Color.DarkGray),
            contentPadding = PaddingValues(horizontal = 8.dp, vertical = 32.dp),
            verticalArrangement = Arrangement.Center,
        ) {
            item { ListHeader { Text("List Screen") } }
            items(5) { index ->
                CompactChip(
                    modifier = Modifier.padding(vertical = 4.dp),
                    onClick = { navController.navigate("detail/$index") },
                    label = {
                        Text(
                            text = "Item $index",
                            textAlign = TextAlign.Center,
                            modifier = Modifier.fillMaxSize(),
                        )
                    },
                )
            }
        }
    }
    composable(
        route = "detail/{Id}",
        arguments = listOf(navArgument("Id") { type = NavType.IntType }),
    ) { backStackEntry ->
        val itemId = backStackEntry.arguments?.getInt("Id") ?: 0
        Column(
            modifier = Modifier.fillMaxSize().background(Color.DarkGray),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center,
        ) {
            ListHeader { Text("Details Screen") }
            Text("Item $itemId")
        }
    }
}
Parameters
navController: NavHostController

The navController for this host

startDestination: String

The route for the start destination

modifier: Modifier = Modifier

The modifier to be applied to the layout

userSwipeEnabled: Boolean = true

Boolean Whether swipe-to-dismiss gesture is enabled.

state: SwipeDismissableNavHostState = rememberSwipeDismissableNavHostState()

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

route: String? = null

The route for the graph

builder: NavGraphBuilder.() -> Unit

The builder used to construct the graph