Как реализовать анимацию translate + scale в Jetpack Compose?
У меня есть экран с изображением в одном углу экрана, и я хочу анимировать его в центре экрана. Что-то вроде перехода от
Icon(
painter = //,
contentDescription = //,
modifier = Modifier.size(36.dp)
)
к
Icon(
painter = //,
contentDescription = //,
modifier = Modifier.fillMaxSize()
)
Первый находится в верхнем левом углу экрана, а второй - в центре. Как я могу перемещаться между двумя состояниями?
2 ответа
Чтобы анимация работала в Compose, вам нужно анимировать значение определенного модификатора. Невозможно использовать анимацию между разными наборами модификаторов.
Следуя этому параграфу документации, вы можете анимировать значение для
Modifier.size
.
Сначала я жду, пока определится размер изображения, с этим значением
size
модификатор можно установить (я использую
then
с пустым
Modifier
перед этим), а затем это значение можно анимировать.
Вот пример:
val animatableSize = remember { Animatable(DpSize.Zero, DpSize.VectorConverter) }
val (containerSize, setContainerSize) = remember { mutableStateOf<DpSize?>(null) }
val (imageSize, setImageSize) = remember { mutableStateOf<DpSize?>(null) }
val density = LocalDensity.current
val scope = rememberCoroutineScope()
Button(onClick = {
scope.launch {
if (imageSize == null || containerSize == null) return@launch
val targetSize = if (animatableSize.value == imageSize) containerSize else imageSize
animatableSize.animateTo(
targetSize,
animationSpec = tween(durationMillis = 1000)
)
}
}) {
Text("Animate")
}
Box(
Modifier
.padding(20.dp)
.size(300.dp)
.fillMaxSize()
.background(Color.LightGray)
.onSizeChanged { size ->
setContainerSize(
with(density) { size.toSize().toDpSize() }
)
}
) {
Image(
Icons.Default.PriorityHigh,
contentDescription = null,
modifier = Modifier
.then(
Modifier.run {
if (animatableSize.value != DpSize.Zero) {
size(animatableSize.value)
} else {
this
}
}
)
.onSizeChanged { size ->
if (imageSize != null) return@onSizeChanged
val dpSize = with(density) { size.toSize().toDpSize() }
setImageSize(dpSize)
scope.launch {
animatableSize.snapTo(dpSize)
}
}
)
}
Результат:
Что-то простое:
@Composable
fun DUM_E(){
val modifier = Modifier.animateContentSize()
Icon(
modifier =
if(triggered) modifier.fillMaxSize()
else modifier.size(36.dp)
)
}
Если вы хотите также анимировать смещение, просто оставьте комментарий ниже, и я, возможно, изменю ответ.