I want two composables to begin and play their animation at the same time. For instance, this is my set up:
LazyColumn(
.semantics(mergeDescendants = true) { contentDescription = contentDes }
) {
item {
ShimmeringComposable() // takes up a lot of the page
}
item {
Spacer()
}
item {
ShimmeringComposable() // under the fold (off the screen)
}
}
I'm noticing that most of the time, the first composable's animation starts to play first, before the second composable's animation. This also sometimes happens if the first composable is visible in the layout and the second composable is off screen.
Is there a way to "sync" the two and make them start/play their animations at the same time?
This code is based on that in this YouTube video tutorial: https://www.youtube.com/watch?v=NyO99OJPPec
@Composable
fun ShimmeringComposable() {
Box(Modifier
.size(50.dp)
.shimmer()
)
}
fun Modifier.shimmer(): Modifier = composed {
var size by remember {
mutableStateOf(IntSize.Zero)
}
val width = size.width.toFloat()
val height = size.height.toFloat()
val transition = rememberInfiniteTransition()
val startOffsetX by transition.animateFloat(
initialValue = -2 * width,
targetValue = 2 * width,
animationSpec = infiniteRepeatable(
animation = tween(
durationMillis = 1000,
)
)
)
background(
brush = Brush.linearGradient(
colors = listOf(Color.gray,Color.white,Color.gray),
start = Offset(startOffsetX, 0),
end = Offset(startOffsetX + width, height)
)
).onGloballyPositioned { size = it.size }
}
UPDATE: Added more code for clarity
EDIT: I think I understand what the issue is. For InfiniteTransition, the animation starts on composition, and a LazyColumn will compose items that are visible on the screen. However, for those that are off screen will not be composed until they come into view (user scrolled down). Wrapping all of the shimmering in a Column
could mitigate this since, as long as you don't use a lot of the shimmering composables as Column isn't as performant as LazyColumn.