👍
KMP Jetpack Compose で animation
LazyList で並べた Card にアニメーションを入れる。
Card 上に配置されたボタンをタップすると、アニメーション実行。
出来上がり画面
AnimatedVisibility を使います
の記載通り
コード
カード全体
- ボタンのところ onClick で
visible
のステートを変更する -
LaunchedEffect
で enter -> exit するように調整。(これがないと1回タップすると enter 部分、もう1回タップすると exit 部分になってしまう)
@Composable
fun CardItemView(
item: FakeCardItem,
cardHeight: Int = 80,
) {
var visible by remember { mutableStateOf(false) }
LaunchedEffect(visible) {
// 一定時間後に非表示にする
if (visible) {
delay(1000)
visible = false
}
}
OutlinedCard {
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
Box(
modifier = Modifier
.weight(1f, fill = true)
.height(cardHeight.dp)
) {
CardMainBox(item)
AnimatedBox(visible)
}
FilledTonalButton(
onClick = { visible = !visible },
shape = RoundedCornerShape(8.dp),
modifier = Modifier.size(cardHeight.dp),
) {
Icon(
Icons.Default.ThumbUp,
contentDescription = "done"
)
}
}
}
}
アニメーションして入り込んでくる部分
- 配置してあるボタン側からアニメーションが入り込んでくるようにしたかったので
enter
,exit
を少し調整
@OptIn(ExperimentalResourceApi::class)
@Composable
private fun AnimatedBox(
visible: Boolean,
) {
AnimatedVisibility(
visible = visible,
enter = slideInHorizontally (
initialOffsetX = {400},
),
exit = shrinkHorizontally (
shrinkTowards = Alignment.End,
)
) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier.fillMaxSize()
.background(Color.Yellow)
) {
Image(
painter = painterResource(Res.drawable.compose_multiplatform),
contentDescription = "dummy image",
)
}
}
}
KMP と書いてあるが、Res.drawable
のあたりくらいしか KMP 用の部分はない。
元々表示されてるカード部分(特に面白いところはない)
@Composable
private fun CardMainBox(
item: FakeCardItem
) {
Column(
horizontalAlignment = Alignment.Start,
verticalArrangement = Arrangement.SpaceAround,
modifier = Modifier.fillMaxSize()
.padding(horizontal = 16.dp, vertical = 8.dp),
) {
Text(
item.title,
maxLines = 1
)
Text(
item.summary,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
)
}
}
つぶやき
アニメーションを一定時間後にOFFする方法がよくわからなくてつまづいた。
LaunchedEffect
で一定時間待って state 戻せば良いだけ。。と気づくまで結構時間がかかってしまった。
あと最初は Jetpack Compose で Android 用の view のみで書いてたので
Image
部分に Lottie を使って可愛いアニメーション付きでやってたのだが
サンプルコードを public repository に載せとこうと思った段階で
欲を出して iOS でも動くように Compose Multiplatform にしたら
Lottie compose は Android 専用です との記載を見つけてやむなく単なる Image にした。
残念・・
まだ Compose Multiplatform どこまで使うか難しいとこですね。
sample repository
参考
Animation on Jetpack compose
Discussion