Mark
06/24/2023, 7:44 AMFlowRow?Uchenna Okoye
06/25/2023, 3:38 PMFlowRow in the past.Rebecca Franks
06/26/2023, 7:39 AMAnimatedVisibility inside FlowRow/FlowColumn, or animate the size of the composables using animateAsState values too. Here is an example using AnimatedVisibility with `FlowRow`:
@OptIn(ExperimentalLayoutApi::class)
@Preview
@Composable
fun FlowLayout_AnimateItemEntrance() {
var numberItems by remember {
mutableIntStateOf(1)
}
LaunchedEffect(Unit){
this.launch {
delay(2000)
numberItems += 1
delay(2000)
numberItems += 1
delay(2000)
numberItems += 1
}
}
FlowRow(
modifier = Modifier.padding(4.dp),
horizontalArrangement = Arrangement.spacedBy(4.dp),
maxItemsInEachRow = 3
) {
val itemModifier = Modifier
.clip(RoundedCornerShape(8.dp))
if (numberItems >= 1) {
Box(modifier = itemModifier
.height(200.dp)
.width(60.dp)
.background(Color.Red))
}
AnimatedVisibility(numberItems >= 2, enter = fadeIn()) {
Box(modifier = itemModifier
.height(200.dp)
.fillMaxWidth(0.7f)
.background(Color.Blue)
)
}
AnimatedVisibility(numberItems >= 3, enter = fadeIn(),
modifier = Modifier.weight(1f)){
Box(modifier = itemModifier
.height(200.dp)
.fillMaxSize(1f)
.background(Color.Magenta))
}
}
}Mark
06/26/2023, 12:29 PMRecyclerView that was using a flow layout manager so the animations of insertion/deletion were automatically happening. I guess what I’m really looking for is LazyFlowRow. In my case, the items are chips. The user can enter action mode and select any subset of chips and then delete/move the selected ones, so it would be good to somehow get the changes to animate. From your example, I’m not sure I can use the same approach, but feel free to correct me!Stylianos Gakis
06/26/2023, 12:33 PManimateItemPlacement inside LazyX.Mark
06/26/2023, 12:34 PMMark
06/26/2023, 12:36 PMLazyFlowRow would also be useful because potentially the items could be considerably too many to fit on the screen at once.Stylianos Gakis
06/26/2023, 12:41 PMMark
06/26/2023, 2:41 PMModifier.animatePlacement() works perfectly! Almost too easy 🙂 I also added the key(item) { } although it seems unnecessary and I’m not clear why it should be used here.Stylianos Gakis
06/26/2023, 2:46 PMMark
06/26/2023, 2:53 PManimatePlacement given here: https://developer.android.com/reference/kotlin/androidx/compose/ui/layout/package-summary#(androidx.compose.ui.Modifier).onPlaced(kotlin.Function1)
Strangely it’s working on one of my FlowRow s but not the other. Investigating…Mark
06/26/2023, 3:34 PMMark
06/26/2023, 6:36 PMStylianos Gakis
06/26/2023, 6:43 PMMark
06/27/2023, 5:17 AMkey(item) by default was because that’s what examples I saw were using.Mark
06/27/2023, 6:55 AMStylianos Gakis
06/27/2023, 7:18 AMkey a lot to see if it happens there too) is that you are reading this state from a parameter passed into the composable, so it’s not from inside a State object, so it’s somehow referencing the old value which was captured in the key lambda. And if you do a rememberUpdatedState outside of that key lambda and then inside read from the result of rememberUpdatedState then it would read the most fresh value.
This is something that happens with functions that capture such parameters, here’s one example https://kotlinlang.slack.com/archives/CJLTWPH7S/p1678750942883689?thread_ts=1678732457.665529&cid=CJLTWPH7S so I don’t know, maybe you’re experiencing something similar?Mark
06/27/2023, 7:33 AMitems.forEach { item ->
val updatedLambda by rememberUpdatedState(item.labelGetter)
key(item.id) {
val label = updatedLambda()
TagChip(
label = label,Stylianos Gakis
06/27/2023, 7:36 AMkey fixes this issue, and if yes there must be something with the key function that I do not properly understand.Mark
06/27/2023, 7:55 AMText Composable , it’s logging the new value. So it’s definitely not a problem with the item itself. How can it be that the Text is not showing the argument that it’s receiving? Perhaps an issue with FlowRow?Mark
06/27/2023, 8:02 AMval label = item.labelGetter()
key(item.id, label) {Stylianos Gakis
06/27/2023, 8:03 AMMark
06/27/2023, 8:03 AMrememberUpdatedState?Stylianos Gakis
06/27/2023, 8:08 AMShivam Dhuria
03/27/2024, 10:02 PMUtkarsh Tiwari
08/06/2024, 4:28 PManimatePlacement() isn't working with FlowRow for me.Utkarsh Tiwari
08/07/2024, 12:22 AM@Composable
@OptIn(ExperimentalLayoutApi::class)
private fun PotentialTripsBlock(spacing: Dp, itemsPerRow: Int) {
Column(verticalArrangement = Arrangement.spacedBy(spacing)) {
EGDSText(
text = "Flow Row (Animating items)",
egdsTextStyle = EGDSTextStyle.Text500(weight = EGDSTextWeight.MEDIUM)
)
val removedList = remember { mutableStateListOf<Int>() }
val items = List(10) { it }
FlowRow(
modifier = Modifier
.fillMaxWidth()
.animateContentSize(),
maxItemsInEachRow = itemsPerRow,
horizontalArrangement = Arrangement.spacedBy(mediumSpacing),
verticalArrangement = Arrangement.spacedBy(spacing),
) {
items.forEachIndexed { index, item ->
key(index) {
AnimatedVisibility(
modifier = Modifier.animatePlacement(),
visible = removedList.contains(index).not(),
enter = fadeIn(),
exit = fadeOut(),
) {
Box(
modifier = Modifier
.widthIn(min = 290.dp)
.height(100.dp)
.background(color = Color.Red)
.clickable {
removedList.add(index)
}
) {}
}
}
}
}
}
}Stylianos Gakis
08/07/2024, 7:52 AManimatePlacement does seem to work after all right?Utkarsh Tiwari
10/08/2024, 5:37 PMRow or LazyRow. It slows down the scrolling. So it only works with FlowRow/Column apparently.