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.