I have a SwipeToDismiss like this :
@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun SwipeToDeleteCard(
onClick: (courseUuid: String) -> Unit,
onSwipeToDelete: (courseUuid: String) -> Unit,
myModel: MyModel,
) {
SwipeToDismiss(
state = rememberDismissState(
confirmStateChange = { dismissValue ->
if (dismissValue == DismissValue.DismissedToStart) {
onSwipeToDelete(course.uuid)
false
} else {
true
}
}
),
directions = setOf(EndToStart),
background = {
Box(
modifier = Modifier
.fillMaxSize()
) {
Icon(
painter = painterResource(id = R.drawable.trash),
tint = Color.Unspecified,
contentDescription = "Delete",
modifier = Modifier
.size(24.dp)
.align(Alignment.CenterEnd)
)
}
},
dismissContent = {
MyCard(
myModel = myModel,
onClick = onClick
)
}
)
}
All my composables are on a SwipeToDismissBox (to make possible back swiping from start to end) :
SwipeToDismissBox(
onDismissed = onDismiss,
modifier = Modifier.fillMaxSize()
) { isBackground ->
if (isBackground) {
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colors.background)
)
return@SwipeToDismissBox
}
Scaffold(
timeText = timeText,
content = content,
modifier = Modifier
.fillMaxSize()
.padding(horizontal = horizontalPadding)
)
}
The problem I'm facing is that it's impossible to swipe from start to end on my card because the swipe is controlled by SwipeToDismiss. I would like to enable swiping only from end to start on my card to delete it, while reserving the swipe from start to end for going back to the previous screen using SwipeToDismissBox. Is it possible?
Any suggestions on how to achieve this behavior would be greatly appreciated. Thank you!
This problem should be tackled with the use of the edgeSwipeToDismiss modifier. The documentation points to a sample of this working as intended.
See code below as sample:
val state = rememberSwipeToDismissBoxState()
val horizontalScrollState = rememberScrollState(0)
SwipeToDismissBox(
state = state,
onDismissed = {},
modifier = Modifier.fillMaxSize()
) { isBackground ->
if (isBackground) {
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colors.background)
)
return@SwipeToDismissBox
}
Box(modifier = Modifier.fillMaxSize()) {
// sample from: https://github.com/androidx/androidx/blob/52b896a78be640852f91b3e792d17baa792e19aa/wear/compose/compose-foundation/samples/src/main/java/androidx/wear/compose/foundation/samples/SwipeToRevealSample.kt#L57
SwipeToReveal(
action = {
Box(
modifier = Modifier
.fillMaxSize()
.clickable { /* Add the primary action */ },
) {
Icon(
imageVector = Icons.Outlined.Delete,
contentDescription = "Delete"
)
}
},
modifier = Modifier
.padding(top = 80.dp)
.edgeSwipeToDismiss(state),
undoAction = {
Chip(
modifier = Modifier.fillMaxWidth(),
onClick = { /* Add undo action here */ },
colors = ChipDefaults.secondaryChipColors(),
label = { Text(text = "Undo") }
)
}
) {
Chip(
modifier = Modifier.fillMaxWidth(),
onClick = { /* the click action associated with chip */ },
colors = ChipDefaults.secondaryChipColors(),
label = { Text(text = "Swipe Me") }
)
}
// sample from: https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:wear/compose/compose-material/samples/src/main/java/androidx/wear/compose/material/samples/SwipeToDismissBoxSample.kt;l=151
Text(
modifier = Modifier
.padding(top = 60.dp, start = 0.dp)
.align(Alignment.Center)
.edgeSwipeToDismiss(state)
.horizontalScroll(horizontalScrollState),
text = "This text can be scrolled horizontally - to dismiss, swipe " +
"right from the left edge of the screen (called Edge Swiping)",
)
}
}
}
However, I tried to use it with SwipeToDismiss
and did not succeed. See below for reference my MVCE comparing the usage in both components, where it works for Text but not for SwipeToDismiss:
val state = rememberSwipeToDismissBoxState()
val horizontalScrollState = rememberScrollState(0)
val dismissState = rememberDismissState()
SwipeToDismissBox(
state = state,
onDismissed = {},
modifier = Modifier.fillMaxSize()
) { isBackground ->
if (isBackground) {
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colors.background)
)
return@SwipeToDismissBox
}
Box(modifier = Modifier.fillMaxSize()) {
SwipeToDismiss(
modifier = Modifier
.padding(top = 80.dp, start = 0.dp)
.edgeSwipeToDismiss(state),
state = dismissState,
directions = setOf(DismissDirection.EndToStart),
background = { },
dismissContent = {
Button(
onClick = { },
) {
Text(text = "button")
}
}
)
Text(
modifier = Modifier
.padding(top = 60.dp, start = 0.dp)
.align(Alignment.Center)
.edgeSwipeToDismiss(state)
.horizontalScroll(horizontalScrollState),
text = "This text can be scrolled horizontally - to dismiss, swipe " +
"right from the left edge of the screen (called Edge Swiping)",
)
}
}
SwipeToDismiss
is a component from the mobile version of Compose Material and not from the Wear Compose Material. As per docs:
While it's technically possible to use the mobile version of Compose Material, it is not optimized for the unique requirements of Wear OS. In addition, mixing Compose Material with Compose Material for Wear OS can result in unexpected behavior.