AnimatedVisibilityとトランジション
コンテンツの表示と非表示をアニメーションさせます。
「AnimatedVisibilityとトランジション」はCoddyKit上の無料Android Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAndroid Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Android Academyコースには全4レッスンが含まれています。
表示をアニメーションさせる
コンテンツが突然表示・非表示になると、不自然な印象を与えます。ComposeのAnimatedVisibilityは、コンポーザブルがレイアウトに入るときと出るときにアニメーションさせます。
コンテンツをこのAPIでラップし、ブール値で表示状態を制御します。ブール値が変わると、瞬時に切り替わる代わりに、Composeが表示または非表示のアニメーションを実行します。
@Composable
fun Greeting(show: Boolean) {
AnimatedVisibility(visible = show) {
Text("Welcome aboard!")
}
}表示・非表示のトランジション
enter パラメータと exit パラメータを使うと、コンテンツの表示と非表示の方法を細かく選べます。一般的な構成要素には、fadeIn/fadeOut、slideIn/slideOut、expandVertically/shrinkVertically などがあります。
+ 演算子で組み合わせると、複数のアニメーションを同時に実行できます。
@Composable
fun Toast(show: Boolean) {
AnimatedVisibility(
visible = show,
enter = fadeIn() + slideInVertically { it },
exit = fadeOut() + slideOutVertically { it }
) {
Text("Item added to cart")
}
}トランジション仕様を調整する
各表示・非表示トランジションは animationSpec を受け取るため、animate*AsState と同じように、時間とイージングを制御できます。
ここではコンテンツが300ミリ秒かけてフェードインし、フェードアウトはより速い150ミリ秒で行われます。これは、閉じる操作をきびきびと感じさせる一般的なパターンです。
AnimatedVisibility(
visible = show,
enter = fadeIn(animationSpec = tween(300)),
exit = fadeOut(animationSpec = tween(150))
) {
Card { Text("Details") }
}展開と縮小
より多くのコンテンツを表示するセクションでは、expandVertically と shrinkVertically を使って高さをアニメーションさせ、周囲のコンテンツを滑らかに押しのけます。
折りたたみ可能なパネル、FAQ項目、「もっと見る」セクションなどに最適です。
@Composable
fun Details(expanded: Boolean) {
AnimatedVisibility(
visible = expanded,
enter = expandVertically() + fadeIn(),
exit = shrinkVertically() + fadeOut()
) {
Text("Extra details revealed when expanded.")
}
}updateTransition:1つの状態から複数の値を制御する
1つの状態に応じて複数のプロパティを一緒に変更する場合、updateTransition がそれらを調整します。子要素がすべて同期してアニメーションする Transition オブジェクトを作成します。
状態を定義し、その状態に応じた各プロパティの関数として、animateColor、animateDp などを使用します。
enum class BoxState { Collapsed, Expanded }
@Composable
fun MorphingBox(state: BoxState) {
val transition = updateTransition(state, label = "box")
val size by transition.animateDp(label = "size") {
if (it == BoxState.Expanded) 200.dp else 100.dp
}
val color by transition.animateColor(label = "color") {
if (it == BoxState.Expanded) Color.Magenta else Color.Cyan
}
Box(Modifier.size(size).background(color))
}トランジションでプロパティごとにタイミングを設定する
updateTransition の大きな利点は、プロパティごとにタイミングを設定できることです。それぞれの animate* 子要素に独自の transitionSpec を指定できるため、同じ状態によって調整しながら、色とサイズを異なる速度で変化させられます。
val size by transition.animateDp(
transitionSpec = { tween(durationMillis = 300) },
label = "size"
) { if (it == BoxState.Expanded) 200.dp else 100.dp }
val corner by transition.animateDp(
transitionSpec = { tween(durationMillis = 600) },
label = "corner"
) { if (it == BoxState.Expanded) 0.dp else 24.dp }AnimatedContent:コンテンツを切り替える
表示状態だけでなく、コンテンツ自体が変化する場合は AnimatedContent を使用します。古いコンテンツと新しいコンテンツの間をアニメーションさせ、デフォルトではクロスフェードします。
カウンター、ステップインジケーター、読み込み中と読み込み完了の状態の切り替えなどに適しています。
@Composable
fun Counter(count: Int) {
AnimatedContent(
targetState = count,
label = "counter"
) { value ->
Text("$value", style = MaterialTheme.typography.headlineLarge)
}
}AnimatedContentのトランジションをカスタマイズする
transitionSpec を使って、AnimatedContent の切り替え方法をカスタマイズできます。カウンターでは、新しい値を上へスライドさせ、古い値をスライドさせて退出させながら、フェードも組み合わせる方法がよく使われます。
using キーワードで SizeTransform を関連付けると、コンテナのサイズも滑らかに変更できます。
AnimatedContent(
targetState = count,
transitionSpec = {
(slideInVertically { it } + fadeIn()) togetherWith
(slideOutVertically { -it } + fadeOut())
},
label = "counter"
) { value -> Text("$value") }リスト項目をアニメーションさせる
LazyColumn 内では、追加、削除、移動された項目を、各項目のコンテンツに Modifier.animateItem() を指定することで、所定の位置へアニメーションさせられます。
手動で状態を管理しなくても、並べ替えや挿入を滑らかに実行できます。
LazyColumn {
items(tasks, key = { it.id }) { task ->
Text(
task.title,
modifier = Modifier.animateItem()
)
}
}画面全体をクロスフェードする
Crossfade は、2つの状態間をフェードさせるシンプルで目的を絞ったヘルパーです。画面全体や主要なUI状態の切り替えに適しています。
現在の状態とコンテンツラムダを渡します。状態が変わると、Crossfadeが古いコンテンツをフェードアウトし、新しいコンテンツをフェードインします。
@Composable
fun ScreenHost(screen: Screen) {
Crossfade(targetState = screen, label = "screen") { current ->
when (current) {
Screen.Home -> HomeScreen()
Screen.Profile -> ProfileScreen()
}
}
}表示時の子要素を調整する
AnimatedVisibility ブロック内では AnimatedVisibilityScope を使用でき、そこから Modifier.animateEnterExit() を利用できます。これにより、個々の子要素に独自の表示・非表示アニメーションを設定し、親のトランジションに重ねて実行できます。
たとえば、パネルをスライドインさせ、その少し後にタイトルをフェードインさせることで、レイヤー感のある効果を作れます。
AnimatedVisibility(visible = show, enter = slideInVertically()) {
Column {
Text(
"Title",
modifier = Modifier.animateEnterExit(
enter = fadeIn(tween(delayMillis = 100))
)
)
Text("Body")
}
}確認問題
数字3から数字4への切り替えを、新しい値をフェードインおよびスライドインさせながらアニメーションさせたいとします。最適なAPIはどれですか?
まとめ:表示とトランジション
これで、コンテンツの表示、非表示、変更をアニメーションさせられるようになりました。
AnimatedVisibilityは、fadeIn/Out、slideIn/Out、expand/shrinkによって表示・非表示をアニメーションさせます。これらは+で組み合わせられます。updateTransitionは、1つの状態から複数の値を調整し、それぞれに独自の仕様を設定できます。AnimatedContentは異なるコンテンツ間の切り替えをアニメーションさせます。Crossfadeはシンプルなフェード版です。Modifier.animateItem()は、リストへの挿入や並べ替えをアニメーションさせます。
次は、ジェスチャーと物理ベースのスプリングアニメーションを使って、自然でインタラクティブな動きを作ります。
よくある質問
「AnimatedVisibilityとトランジション」レッスンは無料ですか?
はい。「AnimatedVisibilityとトランジション」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Android Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Android Academyコースには全4レッスンが含まれています。
「AnimatedVisibilityとトランジション」で何を学びますか?
コンテンツの表示と非表示をアニメーションさせます。 ブラウザで直接実行するハンズオンコードでAndroid Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Android Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのAndroid Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「AnimatedVisibilityとトランジション」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このAndroid Academyレッスンでコードを書いて実行できますか?
はい。すべてのAndroid Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- アニメーションが重要な理由
- animate*AsStateの基本
- AnimatedVisibilityとトランジション
- ジェスチャーとスプリングアニメーション