Hi, I'm wondering if there's a way to disable the ...
# compose-wear
v
Hi, I'm wondering if there's a way to disable the swipeToDismiss action for a fitness screen, similar to the workout in progress screen on the google fit app. I intend to add a button to do the same, but swiping doesn't really work for the UI I'm planning
a
What do you mean by "fitness screen"? Swipe to dismiss is implemented on compose for wear with the swipe to dismiss nav host or the swipe to dismiss box. Are you using one of these?
y
If you need a particular screen to handle swipe to dismiss differently, you can create a SwipeToDismissBoxState (IIRC) manually and pass it in.
v
@yschimke How do I setup the SwipeToDismissBoxState object so that the Swipe to dismiss event is completely disabled?
@Ataul Munim By fitness screen, I mean a screen that's displaying an ongoing fitness related activity, like an active run for example. I don't want the swipe to dismiss to be an option on this screen.
a
Oh right, are you using single activity arch with a swipe to dismiss nav host?
v
Yes, I'm currently experimenting with that pattern. However, swipe to dismiss is enabled even if I use a composable with a scaffold.
y
I'm not sure we have a clean sample, and I haven't tried that case myself. But I hope it should work. See https://developer.android.com/reference/kotlin/androidx/wear/compose/material/package-summary#(androidx.compose.ui.Modi[…]droidx.compose.ui.unit.Dp)
a
@Vivian Thayil is that the WearNavScaffold from horologist?
y
Limits swipe to dismiss to be active from the edge of the viewport only. Used when the center of the screen needs to be able to handle horizontal paging, such as 2-d scrolling a Map or swiping horizontally between pages. Swipe to the right is intercepted on the left part of the viewport with width specified by
edgeWidth
, with other touch events ignored - vertical scroll, click, long click, etc.
You would share the SwipeToDismissBoxState between the SwipeDismissableNavHost and the edgeSwipeToDismiss modifier on the element you want to be scrollable
v
@Ataul Munim @yschimke any ideas?
a
I'll have a look now. What component are you using for the paging?
I didn't repro with a horizontal viewpager but I did try with a Row that had a horizontal scroll modifier and it seemed to work for me, if I ordered the modifiers particularly.
Copy code
@Composable
fun WearApp() {
    val boxState = rememberSwipeToDismissBoxState()
    val navController = rememberSwipeDismissableNavController()
    val navHostState = rememberSwipeDismissableNavHostState(boxState)
    EdgeSwipeTheme {
        SwipeDismissableNavHost(
            navController = navController,
            startDestination = SCREEN_HOME,
            state = navHostState
        ) {
            // start screen - can navigate to settings/active_exercise
            composable(SCREEN_HOME) {
                Home(
                    onClickActiveExercise = {
                        navController.navigate(SCREEN_ACTIVE_EXERCISE)
                    },
                    onClickSettings = {
                        navController.navigate(SCREEN_SETTINGS)
                    }
                )
            }

            // can swipe back to home
            composable(SCREEN_SETTINGS) {
                Settings()
            }

            // has a horizontal viewpager, CANNOT swipe back to home
            composable(SCREEN_ACTIVE_EXERCISE) {
                ActiveExercise(boxState)
            }
        }
    }
}
Here is where we're setting the
edgeSwipeToDismiss
modifier on the composable which supports horizontal swiping. In your case it'll be the paging composable. Note the
0.dp
as the second parameter.
Copy code
@Composable
private fun ActiveExercise(
    boxState: SwipeToDismissBoxState
) {
    val scrollState = rememberScrollState()
    Row(
        modifier = Modifier
            .edgeSwipeToDismiss(boxState, 0.dp)
            .horizontalScroll(scrollState)
            .fillMaxHeight()
            .background(MaterialTheme.colors.background),
        verticalAlignment = Alignment.CenterVertically
    ) {
        Text(
            modifier = Modifier.width(100.dp),
            textAlign = TextAlign.Center,
            color = MaterialTheme.colors.primary,
            text = SCREEN_ACTIVE_EXERCISE
        )

        Text(
            modifier = Modifier.width(100.dp),
            textAlign = TextAlign.Center,
            color = MaterialTheme.colors.primary,
            text = SCREEN_ACTIVE_EXERCISE
        )

        Text(
            modifier = Modifier.width(100.dp),
            textAlign = TextAlign.Center,
            color = MaterialTheme.colors.primary,
            text = SCREEN_ACTIVE_EXERCISE
        )
    }
}
here are the remaining screens for the example. There's nothing special here.
Copy code
@Composable
private fun Settings() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(MaterialTheme.colors.background),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(
            modifier = Modifier.fillMaxWidth(),
            textAlign = TextAlign.Center,
            color = MaterialTheme.colors.primary,
            text = SCREEN_SETTINGS
        )
    }
}

@Composable
private fun Home(
    onClickActiveExercise: () -> Unit,
    onClickSettings: () -> Unit,
) {

    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(MaterialTheme.colors.background),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(
            modifier = Modifier.fillMaxWidth(),
            textAlign = TextAlign.Center,
            color = MaterialTheme.colors.primary,
            text = SCREEN_HOME
        )
        Button(onClick = onClickActiveExercise) {
            Text(text = SCREEN_ACTIVE_EXERCISE)
        }
        Button(onClickSettings) {
            Text(text = SCREEN_SETTINGS)
        }
    }
}

private const val SCREEN_HOME = "screen_home"
private const val SCREEN_SETTINGS = "screen_settings"
private const val SCREEN_ACTIVE_EXERCISE = "screen_active_exercise"
here, only home and settings support swipe to dismiss. in the activeExercise composable, by setting "0" as the value in the
edgeSwipeToDismiss
modifier, it effectively disables swipe to dismiss.
594 Views