如何在 Jetpack Compose 中实现平移+缩放动画?
How to implement a translate + scale animation in Jetpack Compose?
我有一个屏幕,屏幕的一角有一个图像,我想将它设置为动画到屏幕中央。
有点像从
Icon(
painter = //,
contentDescription = //,
modifier = Modifier.size(36.dp)
)
至
Icon(
painter = //,
contentDescription = //,
modifier = Modifier.fillMaxSize()
)
第一个放在屏幕的左上角,第二个在中间。如何在两种状态之间设置动画?
要使动画在 Compose 中工作,您需要为某个特定修饰符的值设置动画。无法在不同的修改器集之间设置动画。
在 this 文档段落之后,您可以为 Modifier.size
设置动画值。
首先我等待确定图像的大小,使用这个值可以设置 size
修饰符(我使用 then
之前有一个空的 Modifier
)然后可以对这个值进行动画处理。
这是一个示例:
Column {
val animatableSize = remember { Animatable(Size.Zero, Size.VectorConverter) }
val (containerSize, setContainerSize) = remember { mutableStateOf<Size?>(null) }
val (imageSize, setImageSize) = remember { mutableStateOf<Size?>(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)
.background(Color.LightGray)
.onSizeChanged { size ->
setContainerSize(size.toSize())
}
) {
Image(
Icons.Default.Person,
contentDescription = null,
modifier = Modifier
.then(
if (animatableSize.value != Size.Zero) {
animatableSize.value.run {
Modifier.size(
width = with(density) { width.toDp() },
height = with(density) { height.toDp() },
)
}
} else {
Modifier
}
)
.onSizeChanged { intSize ->
if (imageSize != null) return@onSizeChanged
val size = intSize.toSize()
setImageSize(size)
scope.launch {
animatableSize.snapTo(size)
}
}
)
}
}
结果:
试试这个:
@Composable
fun DUM_E_MARK_II(triggered: Boolean) {
BoxWithConstraints {
val size by animateDpAsState(if (triggered) 36.dp else maxHeight)
Icon(
imageVector = Icons.Filled.Warning,
contentDescription = "Just a better solution to the problem",
modifier = Modifier.size(size)
)
}
}
我有一个屏幕,屏幕的一角有一个图像,我想将它设置为动画到屏幕中央。 有点像从
Icon(
painter = //,
contentDescription = //,
modifier = Modifier.size(36.dp)
)
至
Icon(
painter = //,
contentDescription = //,
modifier = Modifier.fillMaxSize()
)
第一个放在屏幕的左上角,第二个在中间。如何在两种状态之间设置动画?
要使动画在 Compose 中工作,您需要为某个特定修饰符的值设置动画。无法在不同的修改器集之间设置动画。
在 this 文档段落之后,您可以为 Modifier.size
设置动画值。
首先我等待确定图像的大小,使用这个值可以设置 size
修饰符(我使用 then
之前有一个空的 Modifier
)然后可以对这个值进行动画处理。
这是一个示例:
Column {
val animatableSize = remember { Animatable(Size.Zero, Size.VectorConverter) }
val (containerSize, setContainerSize) = remember { mutableStateOf<Size?>(null) }
val (imageSize, setImageSize) = remember { mutableStateOf<Size?>(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)
.background(Color.LightGray)
.onSizeChanged { size ->
setContainerSize(size.toSize())
}
) {
Image(
Icons.Default.Person,
contentDescription = null,
modifier = Modifier
.then(
if (animatableSize.value != Size.Zero) {
animatableSize.value.run {
Modifier.size(
width = with(density) { width.toDp() },
height = with(density) { height.toDp() },
)
}
} else {
Modifier
}
)
.onSizeChanged { intSize ->
if (imageSize != null) return@onSizeChanged
val size = intSize.toSize()
setImageSize(size)
scope.launch {
animatableSize.snapTo(size)
}
}
)
}
}
结果:
试试这个:
@Composable
fun DUM_E_MARK_II(triggered: Boolean) {
BoxWithConstraints {
val size by animateDpAsState(if (triggered) 36.dp else maxHeight)
Icon(
imageVector = Icons.Filled.Warning,
contentDescription = "Just a better solution to the problem",
modifier = Modifier.size(size)
)
}
}