Okay so I've been trying to implement swipe to delete function in my app. Whenever I swipe one of the items from the list I'm able to see a RedBackground behind and everything works fine. Also the swipe animation when I delete an item is triggered successfully. (Even though I'm not sure if it's a good idea to use delay for that? I can't think of any other way to do it). But the enter animation when I add an item to the database/list is not working, and I'm not sure why. Here's the code of my Lazy Column
@Composable
fun DisplayTasks(
tasks: List<ToDoTask>,
onSwipeToDelete: (Action, ToDoTask) -> Unit,
navigateToTaskScreen: (Int) -> Unit
) {
LazyColumn {
items(
items = tasks,
key = { task ->
task.id
}
) { task ->
val dismissState = rememberDismissState()
val dismissDirection = dismissState.dismissDirection
val isDismissed = dismissState.isDismissed(DismissDirection.EndToStart)
if (isDismissed && dismissDirection == DismissDirection.EndToStart
) {
val scope = rememberCoroutineScope()
scope.launch {
delay(300)
onSwipeToDelete(Action.DELETE, task)
}
}
AnimatedVisibility(
visible = !isDismissed,
exit = shrinkVertically(
animationSpec = tween(
durationMillis = 300,
)
),
enter = expandVertically(
animationSpec = tween(
durationMillis = 300
)
)
) {
SwipeToDismiss(
state = dismissState,
directions = setOf(DismissDirection.EndToStart),
dismissThresholds = { FractionalThreshold(0.2f) },
background = { RedBackground() },
dismissContent = {
LazyColumnItem(
toDoTask = task,
navigateToTaskScreen = navigateToTaskScreen
)
}
)
}
}
}
}
First of all, you shouldn't perform any state changing actions inside composable. Instead use one of side effects, usually LaunchedEffect(key) { }: content of the block will be called on the first render and each time key is different from the last render. Also inside you're already in a coroutine scope, so no need to launch it. Check out more about side-effects in the documentation.
Item animation in the list is not yet supported. It's as simple as adding AnimatedVisibility to the items.
When compose firstly sees AnimatedVisibility in the compose tree, it draws(or not draws) it without animation.
And when on next recomposition visible is different from the last render time, it animates.
So to make it work as you wish you can do the following:
itemAppeared state value, which will make item in the list initially hidden, and using side effect make it visible right after rendercolumnAppeared which will prevent initial appearance animation - without it when screen renders all items will appear animatedly too@Composable
fun DisplayTasks(
tasks: List<ToDoTask>,
onSwipeToDelete: (Action, ToDoTask) -> Unit,
) {
var columnAppeared by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
columnAppeared = true
}
LazyColumn {
items(
items = tasks,
key = { task ->
task.id
}
) { task ->
val dismissState = rememberDismissState()
val dismissDirection = dismissState.dismissDirection
val isDismissed = dismissState.isDismissed(DismissDirection.EndToStart)
if (isDismissed && dismissDirection == DismissDirection.EndToStart
) {
LaunchedEffect(Unit) {
delay(300)
onSwipeToDelete(Action.DELETE, task)
}
}
var itemAppeared by remember { mutableStateOf(!columnAppeared) }
LaunchedEffect(Unit) {
itemAppeared = true
}
AnimatedVisibility(
visible = itemAppeared && !isDismissed,
exit = shrinkVertically(
animationSpec = tween(
durationMillis = 300,
)
),
enter = expandVertically(
animationSpec = tween(
durationMillis = 300
)
)
) {
SwipeToDismiss(
state = dismissState,
directions = setOf(DismissDirection.EndToStart),
dismissThresholds = { FractionalThreshold(0.2f) },
background = {
Box(
Modifier
.background(Color.Red)
.fillMaxSize()
)
},
dismissContent = {
Text(task.id)
}
)
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With