Skip to content

Instantly share code, notes, and snippets.

@raghunandankavi2010
Created May 14, 2023 10:46
Show Gist options
  • Save raghunandankavi2010/0f6ff1e77511bb14d6ec156d994289a9 to your computer and use it in GitHub Desktop.
Save raghunandankavi2010/0f6ff1e77511bb14d6ec156d994289a9 to your computer and use it in GitHub Desktop.
Swipe to dismiss in Lazy Column
@ExperimentalMaterialApi
@Composable
fun Tutorial2_13Screen() {
val viewModel = MyViewModel()
TutorialContent(viewModel)
}
@ExperimentalMaterialApi
@Composable
private fun TutorialContent(viewModel: MyViewModel) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Button(onClick = {
viewModel.newList()
}) {
Text(text = "Generate User List")
}
val usersList = viewModel.listFlow.collectAsState()
// 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 = usersList.value, key = { user -> user.id }) { user ->
val currentItem by rememberUpdatedState(user)
val dismissState = rememberDismissState(
confirmStateChange = { dismissValue ->
when (dismissValue) {
DismissValue.DismissedToEnd -> {
viewModel.removeItem(currentItem)
true
}
DismissValue.DismissedToStart -> {
viewModel.removeItem(currentItem)
true
}
else -> { false }
}
}
)
SwipeToDismiss(
state = dismissState,
modifier = Modifier.padding(vertical = 4.dp),
directions = setOf(StartToEnd, EndToStart),
dismissThresholds = { direction ->
FractionalThreshold(if (direction == StartToEnd) 0.25f else 0.5f)
},
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(user.name, fontWeight = FontWeight.Bold)
},
secondaryText = { Text("Swipe me left or right!") }
)
}
}
)
}
}
}
}
class MyViewModel : ViewModel() {
private var userList = mutableStateListOf<User>()
val listFlow = MutableStateFlow(userList)
fun newList() {
val mutableList = mutableStateListOf<User>()
for (i in 0..10) {
mutableList.add(User(i, "User$i"))
}
userList = mutableList
listFlow.value = mutableList
}
fun removeItem(item: User) {
val index = userList.indexOf(item)
userList.remove(userList[index])
}
}
data class User(val id: Int, val name: String)
@SmartToolFactory
Copy link

Sure, would you mind opening a PR for this? I had taken this example from official docs in 2021

@raghunandankavi2010
Copy link
Author

raghunandankavi2010 commented May 14, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment