はじめに
UI要素を表示させる時にふわっと表示するようにアニメーションさせたくてAnimatedVisibilityを使ったのですが、最初使い方がよく分からなくて間違って使ってたので備忘録としてまとめておきます。
AnimatedVisibilityをif文で囲むとアニメーションしなくなる
通常フラグがtrueの場合のみComposableを表示したい場合は以下のように書きますよね。
@Composable
fun AnimatedScreen(
modifier: Modifier = Modifier
) {
Column(modifier = modifier) {
var showAnimation by remember{ mutableStateOf(false) }
Button(onClick = { showAnimation = !showAnimation }) {
Text(text = "フラグを切り替える")
}
//フラグがtrueの時だけ表示したい
if(showAnimation) {
Text("Hello",
Modifier
.fillMaxWidth()
.height(200.dp))
}
}
}
これをそのまま「条件を満たしたときのみアニメーション付きで表示させたい」と思って以下のように実装すると、
まったくアニメーションせず、AnimatedVisibilityを使わなかった場合と同じ動作になってしまいます。
@Composable
fun AnimatedScreen(
modifier: Modifier = Modifier
) {
Column(modifier = modifier) {
var showAnimation by remember{ mutableStateOf(false) }
Button(onClick = { showAnimation = !showAnimation }) {
Text(text = "フラグを切り替える")
}
//フラグがtrueの時だけアニメーション付きで表示したい
if(showAnimation) {
val density = LocalDensity.current
AnimatedVisibility(
visible = showAnimation,
enter = slideInVertically {
// Slide in from 40 dp from the top.
with(density) { -40.dp.roundToPx() }
},
) {
Text("Hello",
Modifier
.fillMaxWidth()
.height(200.dp))
}
}
}
}
解決策
AnimatedVisibilityを使う場合は以下のようにします。
@Composable
fun AnimatedScreen(
modifier: Modifier = Modifier
) {
Column(modifier = modifier) {
var showAnimation by remember{ mutableStateOf(false) }
Button(onClick = { showAnimation = !showAnimation }) {
Text(text = "フラグを切り替える")
}
//if文は不要!
val density = LocalDensity.current
AnimatedVisibility(
visible = showAnimation,
enter = slideInVertically {
// Slide in from 40 dp from the top.
with(density) { -40.dp.roundToPx() }
},
) {
Text("Hello",
Modifier
.fillMaxWidth()
.height(200.dp))
}
}
}
AnimatedVisibilityの中でBooleanを参照しているので、if文で囲む必要はありません。
さいごに
AnimatedVisibilityに渡すBooleanの意味を考えればうまく動かないのは当たり前なのですが、手癖でよく考えずに実装するとやはりダメですね。