SwipeToDismiss
Composable Component
A composable that can be dismissed by swiping left or right.
Common
@Composable
@ExperimentalMaterialApi
fun SwipeToDismiss(
state: DismissState,
modifier: Modifier = Modifier,
directions: Set<DismissDirection> = setOf(EndToStart, StartToEnd),
dismissThresholds: (DismissDirection) -> ThresholdConfig = {
FixedThreshold(DISMISS_THRESHOLD)
},
background: @Composable RowScope.() -> Unit,
dismissContent: @Composable RowScope.() -> Unit,
) =
BoxWithConstraints(modifier) {
val width = constraints.maxWidth.toFloat()
val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
val anchors = mutableMapOf(0f to Default)
if (StartToEnd in directions) anchors += width to DismissedToEnd
if (EndToStart in directions) anchors += -width to DismissedToStart
val thresholds = { from: DismissValue, to: DismissValue ->
dismissThresholds(getDismissDirection(from, to)!!)
}
val minFactor =
if (EndToStart in directions) StandardResistanceFactor else StiffResistanceFactor
val maxFactor =
if (StartToEnd in directions) StandardResistanceFactor else StiffResistanceFactor
Box(
Modifier.swipeable(
state = state,
anchors = anchors,
thresholds = thresholds,
orientation = Orientation.Horizontal,
enabled = state.currentValue == Default,
reverseDirection = isRtl,
resistance =
ResistanceConfig(
basis = width,
factorAtMin = minFactor,
factorAtMax = maxFactor,
),
)
) {
Row(content = background, modifier = Modifier.matchParentSize())
Row(
content = dismissContent,
modifier = Modifier.offset { IntOffset(state.offset.value.roundToInt(), 0) },
)
}
}
Parameters
state | The state of this component. |
modifier | Optional Modifier for this component. |
directions | The set of directions in which the component can be dismissed. |
dismissThresholds | The thresholds the item needs to be swiped in order to be dismissed. |
background | A composable that is stacked behind the content and is exposed when the content is swiped. You can/should use the state to have different backgrounds on each side. |
dismissContent | The content that can be dismissed. |
Code Examples
SwipeToDismissListItems
@Composable
@OptIn(ExperimentalMaterialApi::class)
fun SwipeToDismissListItems() {
// This is an example of a list of dismissible items, similar to what you would see in an
// email app. Swiping left reveals a 'delete' icon and swiping right reveals a 'done' icon.
// The background will start as grey, but once the dismiss threshold is reached, the colour
// will animate to red if you're swiping left or green if you're swiping right. When you let
// go, the item will animate out of the way if you're swiping left (like deleting an email) or
// back to its default position if you're swiping right (like marking an email as read/unread).
LazyColumn {
items(items) { item ->
var unread by remember { mutableStateOf(false) }
val dismissState =
rememberDismissState(
confirmStateChange = {
if (it == DismissedToEnd) unread = !unread
it != DismissedToEnd
}
)
SwipeToDismiss(
state = dismissState,
modifier = Modifier.padding(vertical = 4.dp),
directions = setOf(StartToEnd, EndToStart),
background = {
val direction = dismissState.dismissDirection ?: return@SwipeToDismiss
val color by
animateColorAsState(
when (dismissState.targetValue) {
Default -> Color.LightGray
DismissedToEnd -> Color.Green
DismissedToStart -> Color.Red
}
)
val alignment =
when (direction) {
StartToEnd -> Alignment.CenterStart
EndToStart -> Alignment.CenterEnd
}
val icon =
when (direction) {
StartToEnd -> Icons.Default.Done
EndToStart -> Icons.Default.Delete
}
val scale by
animateFloatAsState(if (dismissState.targetValue == Default) 0.75f else 1f)
Box(
Modifier.fillMaxSize().background(color).padding(horizontal = 20.dp),
contentAlignment = alignment,
) {
Icon(
icon,
contentDescription = "Localized description",
modifier = Modifier.scale(scale),
)
}
},
dismissContent = {
Card(
elevation =
animateDpAsState(
if (dismissState.dismissDirection != null) 4.dp else 0.dp
)
.value
) {
ListItem(
text = {
Text(item, fontWeight = if (unread) FontWeight.Bold else null)
},
secondaryText = { Text("Swipe me left or right!") },
)
}
},
)
}
}
}
Create your own Component Library
Material Components are meant to be used as is and they do not allow customizations. To build your own Jetpack Compose component library use Compose Unstyled