I want to measure the height of parent view and animate accordingly to that. I tried from this answer. I think it returns 0.dp to me. So what is the proper way of measuring the item?
Actually I want to animate a view, but my view is 0.dp when I run the application.
@Preview(showBackground = true)
@Composable
fun MoveText() {
val density = LocalDensity.current
var columnHeightDp by remember {
mutableStateOf(0.dp)
}
var visible by remember { mutableStateOf(true) }
val iconOffsetAnimation: Dp by animateDpAsState(
if (visible) 13.dp else 0.dp, tween(1000)
)
val textOffsetAnimation: Dp by animateDpAsState(
if (visible) 6.dp else 0.dp, tween(1000)
)
val viewAlpha: Float by animateFloatAsState(
targetValue = if (visible) 1f else 0f, animationSpec = tween(
durationMillis = 1000,
)
)
val heightInDp: Dp by animateDpAsState(
targetValue = if (visible) {
columnHeightDp
} else {
0.dp
}, animationSpec = tween(
durationMillis = 1000,
)
)
ScrollComposeTheme {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp, top = 16.dp)
) {
Column(modifier = Modifier
.onGloballyPositioned { coordinates ->
with(density) {
columnHeightDp = coordinates.size.height.toDp()
}
}
.height(heightInDp)
.background(Color.LightGray)) {
Image(
modifier = Modifier.padding(top = iconOffsetAnimation),
alpha = viewAlpha,
imageVector = Icons.Default.ShoppingCart,
contentDescription = null,
)
Text(
modifier = Modifier.padding(top = textOffsetAnimation),
text = "Hello, Anna",
fontSize = 20.sp,
color = Color.Black.copy(alpha = viewAlpha),
)
}
Button(
modifier = Modifier.padding(top = 10.dp),
onClick = {
visible = !visible
},
) {
Text(text = "Move Text")
}
}
}
}
Actual Output
Expected Output
I tried to achieve something like this demo video from your question.
val modifier: Modifier = Modifier.background(Color.LightGray)
Column(modifier = if (columnHeightDp != 0.dp) {
modifier
.height(heightInDp)
} else {
modifier.onSizeChanged {
with(density) {
columnHeightDp = it.height.toDp()
}
}.wrapContentHeight()
},
) {
// your content goes here...Image and Text
}
Let me explain how i reach to this.
modifier = modifier.onSizeChanged {
with(density) {
columnHeightDp = it.height.toDp()
}
}.wrapContentHeight(),
Here for the dynamic height calculation onSizeChanged
method works well. So i save this in a variable as per your need. The wrapContentHeight
method in modifier is equivalent as WRAP_CONTENT
in xml.
It will work nicely showing both components (Image and Text)(Button). But we need the animation so what we need to do is.
if (columnHeightDp != 0.dp) {
modifier
.height(heightInDp)
}
This will apply the animation for the entire Column
for Image
and Text