🐻❄️
Jetpack Compose の Animated Visibility について深堀りする
はじめに
- AnimatedVisibility は View の Visibility 変化させるアニメーション
- AnimatedVisibility は特に動きのある表示・非表示を単一の View に対して実現したいときに利用する
- AnimatedVisibility では引数に与える Editable もしくは MutableTransitionState を変化させることでアニメーションを動作させる
Editable(Boolean) でアニメーションを動作させる
- Editable(Boolean) を remember で定義し変化させる
- Editable(Boolean) を変化させると、それに応じてアニメーションが動作する
@ExperimentalAnimationApi
@Composable
fun AnimatedVisibilitySample() {
var editable by remember { mutableStateOf(true) }
Column(modifier = Modifier.padding(8.dp)) {
Text(
text = "AnimatedVisibility",
style = MaterialTheme.typography.h6
)
AnimatedVisibility(visible = editable) {
Surface(
color = Color.Yellow,
modifier = Modifier
.fillMaxWidth()
.height(100.dp)
.align(Alignment.CenterHorizontally)
.padding(8.dp)
) {}
}
Button(
onClick = { editable = !editable },
modifier = Modifier.fillMaxWidth()
) {
Text(text = "Toggle")
}
}
}
MutableTransitionState でアニメーションを動作させる
- MutableTransitionState を remember で定義する。
- MutableTransitionState を変化させると、それに応じてアニメーションが動作する
- MutableTransitionState には現在の表示状態を表す currentState と現在のアニメーション状況を表す isIdle が含まれる
- そのため currentState と isIdle を組み合わせると表示済み・表示中・非表示・非表示中などの状態を識別できる
@ExperimentalAnimationApi
@Composable
fun AnimatedVisibilityStateSample() {
val state = remember {
MutableTransitionState(false).apply {
targetState = true
}
}
Column(modifier = Modifier.padding(8.dp)) {
Text(
text = "AnimatedVisibilityState",
style = MaterialTheme.typography.h6
)
AnimatedVisibility(visibleState = state) {
Surface(
color = Color.Yellow,
modifier = Modifier
.fillMaxWidth()
.height(100.dp)
.align(Alignment.CenterHorizontally)
.padding(8.dp)
) {
Text(
text = state.getAnimationState().toString()
)
}
}
Button(
onClick = { state.targetState = !state.currentState },
modifier = Modifier.fillMaxWidth()
) {
Text(text = "Toggle")
}
}
}
// 今回はこのような拡張関数を用意してみた、すると簡単にアニメーション状態が取得できる
enum class AnimState {
VISIBLE,
INVISIBLE,
APPEARING,
DISAPPEARING
}
fun MutableTransitionState<Boolean>.getAnimationState(): AnimState {
return when {
this.isIdle && this.currentState -> AnimState.VISIBLE
!this.isIdle && this.currentState -> AnimState.DISAPPEARING
this.isIdle && !this.currentState -> AnimState.INVISIBLE
else -> AnimState.APPEARING
}
}
表示・非表示時のアニメーションを追加できる
- AnimatedVisibility には enter と exit という引数が用意されている
- ここに fadeIn や fadeOut のアニメーションを渡してやると簡単に Visibility が変化したときにアニメーションを追加できる
@ExperimentalAnimationApi
@Composable
fun AnimatedVisibilityEnterExitSample() {
val state = remember {
MutableTransitionState(false).apply {
targetState = true
}
}
Column(modifier = Modifier.padding(8.dp)) {
Text(
text = "AnimatedVisibilityState",
style = MaterialTheme.typography.h6
)
AnimatedVisibility(
visibleState = state,
enter = fadeIn(),
exit = fadeOut()
) {
Surface(
color = Color.Yellow,
modifier = Modifier
.fillMaxWidth()
.height(100.dp)
.align(Alignment.CenterHorizontally)
.padding(8.dp)
) {
Text(text = state.getAnimationState().toString())
}
}
Button(
onClick = { state.targetState = !state.currentState },
modifier = Modifier.fillMaxWidth()
) {
Text(text = "Toggle")
}
}
}
おわりに
- AnimationVisibility では簡単に View の Visibility をアニメーションで切り替えられる
- AnimationVisibility では動きのある表示・非表示を実現するのが得意
Discussion