アニメーションが重要な理由
ユーザーを導き、操作を楽しませる動きを学びます。
「アニメーションが重要な理由」はCoddyKit上の無料Android Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAndroid Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Android Academyコースには全4レッスンが含まれています。
目的のあるモーション
アニメーションは単なる装飾ではありません。優れたAndroidアプリでは、モーションが注意を誘導し、何が変わったのかを説明し、UIを反応性が高く生き生きとしたものにします。
このコースでは、1行で使えるanimate*AsStateヘルパーからAnimatedVisibility、トランジション、物理ベースのスプリングまで、Jetpack ComposeのアニメーションAPIを学びます。
最初のレッスンでは、常に目的を持ってモーションを使えるように、アニメーションを使う理由とタイミングについて学びます。
Composeでは宣言的にアニメーションを使う
Composeでは、フレームごとにアニメーションを手動で開始・停止する必要はありません。代わりに目標値を記述すると、その値が変化したときにComposeが滑らかに目標値へアニメーションさせます。
ここでは、ボックスの色を1つのブール状態で制御しています。タップして状態を切り替えると、色が自動的に滑らかに変化します。
@Composable
fun ColorBox() {
var selected by remember { mutableStateOf(false) }
val color by animateColorAsState(
targetValue = if (selected) Color.Green else Color.Gray,
label = "box-color"
)
Box(
Modifier
.size(120.dp)
.background(color)
.clickable { selected = !selected }
)
}ユーザー操作へのフィードバック
モーションの最も重要な役割の1つがフィードバックです。ユーザーがボタンをタップしたりスイッチを切り替えたりしたとき、小さなアニメーションによってアプリが操作を受け付けたことを確認できます。
瞬間的でぎこちない変化は壊れたように感じられますが、150~300ミリ秒程度の短いトランジションは洗練された印象を与えます。ここでは、押している間だけボタンが少し縮みます。
@Composable
fun PressableButton(onClick: () -> Unit) {
var pressed by remember { mutableStateOf(false) }
val scale by animateFloatAsState(
targetValue = if (pressed) 0.92f else 1f,
label = "press-scale"
)
Button(
onClick = onClick,
modifier = Modifier.graphicsLayer {
scaleX = scale; scaleY = scale
}
) { Text("Tap me") }
}状態の変化を説明する
UIが変化するとき、アニメーションはユーザーが何が起きたのかを理解するのに役立ちます。フェードしながらスライドインする要素は「新しく追加された」と伝わり、フェードアウトする要素は「削除された」と伝わります。
モーションがないと、コンテンツが突然現れたり消えたりするため、何かが表示されたのか、消えたのか、移動したのかをユーザーが理解できないことがあります。
@Composable
fun Banner(visible: Boolean) {
AnimatedVisibility(
visible = visible,
enter = fadeIn() + slideInVertically(),
exit = fadeOut() + slideOutVertically()
) {
Text("Saved successfully!")
}
}連続性と空間感覚
モーションは連続性を保ちます。カードが展開したり要素が新しい位置に移動したりするとき、変化をアニメーションさせることで、ユーザーは画面上の位置関係を把握し続けられます。
Composeでは、Modifier.animateContentSize()を使ってレイアウトの変化を自動的にアニメーションできます。コンテンツが変化すると、ボックスが滑らかに拡大・縮小します。
@Composable
fun ExpandableCard(expanded: Boolean) {
Column(
Modifier
.fillMaxWidth()
.animateContentSize()
.padding(16.dp)
) {
Text("Title", style = MaterialTheme.typography.titleMedium)
if (expanded) {
Text("Here is the longer body that appears when expanded.")
}
}
}期間とタイミングが重要
優れたアニメーションは高速です。ほとんどのUIトランジションは、およそ150~400ミリ秒に収めるべきです。遅すぎるとアプリが重く感じられ、速すぎると動きが見えません。
Composeでは、tweenとeasingカーブを使って、期間と速度の変化を調整できます。イージングによって加速と減速が生まれ、動きが自然に感じられます。
val offset by animateDpAsState(
targetValue = if (open) 0.dp else 200.dp,
animationSpec = tween(
durationMillis = 300,
easing = FastOutSlowInEasing
),
label = "panel-offset"
)やりすぎない
アニメーションは強力である一方、使いすぎやすい機能でもあります。モーションが多すぎると注意をそらし、ユーザーの操作を遅らせ、場合によっては不快感を引き起こします。
基本的な指針:
- 装飾ではなく、伝達のためにアニメーションを使います。
- トランジションは短く控えめにします。
- 画面上のすべてを一度にアニメーションさせるのは避けます。
- アニメーション中にユーザーの操作を妨げてはいけません。
アクセシビリティに配慮する
モーションに敏感なユーザーの中には、システム設定でアニメーションを減らすを有効にしている方もいます。配慮のあるアプリは、その設定を尊重します。
アニメーションの倍率がゼロに設定されているかどうかを読み取り、それに応じて重要でないモーションを減らしたり無効にしたりできます。
@Composable
fun rememberReduceMotion(): Boolean {
val context = LocalContext.current
val scale = Settings.Global.getFloat(
context.contentResolver,
Settings.Global.ANIMATOR_DURATION_SCALE,
1f
)
return scale == 0f
}Composeアニメーションツールボックス
Composeには、レイヤー構造になった複数のアニメーションAPIがあります。このコースでは、次のAPIを学びます。
animate*AsState- 単一の値(色、サイズ、浮動小数点数など)をアニメーションさせます。AnimatedVisibility- 表示と非表示をアニメーションさせます。updateTransition- 複数の値をまとめて調整します。AnimatedContent- 異なるコンテンツ間をクロスフェードします。Animatableとspring- 低レベルで物理ベースの制御を行います。
まずは高レベルAPIから始め、より細かな制御が必要になった場合だけ低レベルAPIを使ってください。
アニメーションは状態に従う
すべてを理解するための重要な考え方は、Composeではアニメーションが状態を追跡するということです。値を変更すると、アニメーションAPIが毎フレーム、UIを新しい値に向けて滑らかに補間します。
つまり、タイムラインを自分で記述することはほとんどありません。「このプロパティはXになるべき」と宣言すれば、Composeがその間のフレームを処理してくれます。
@Composable
fun FadingText(highlighted: Boolean) {
val alpha by animateFloatAsState(
targetValue = if (highlighted) 1f else 0.4f,
label = "text-alpha"
)
Text(
"Status",
modifier = Modifier.graphicsLayer { this.alpha = alpha }
)
}純粋なKotlinで簡単な準備
アニメーションは値と値の間を補間します。その核心にあるのは単純な数学です。0から1までの分数 t を使って、開始値と終了値を混ぜ合わせます。この考え方(線形補間、つまり lerp)が、これから作成するすべてのアニメーションの基礎になります。
この小さな純粋なKotlinのスニペットは、Composeが1秒間に何度も適用している考え方を示しています。
fun lerp(start: Float, end: Float, t: Float): Float =
start + (end - start) * t
fun main() {
for (i in 0..4) {
val t = i / 4f
println("t=$t -> ${lerp(0f, 100f, t)}")
}
}確認問題
Jetpack Composeにおけるアニメーションの基本的な考え方は何ですか?
まとめ:意味のある動き
これで、アニメーションがなぜ重要なのか、そしてその背景にあるモデルを理解できました。
- 動きはフィードバックを提供し、変化を説明し、連続性を保ちます。
- Composeのアニメーションは宣言的で、状態に従います。
- トランジションは短く(約150~400ミリ秒)、目的を持たせてください。使いすぎないことが大切です。
- アクセシビリティのために動きを減らしているユーザーに配慮してください。
- まずは高レベルAPIを使用してください。
animate*AsState、AnimatedVisibility、トランジション、スプリングなどが該当します。
次は、animate*AsStateファミリーを使って単一の値をアニメーションさせます。
AI チューターと学ぶ Kotlin — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 36
- レッスン
- 152
よくある質問
「アニメーションが重要な理由」レッスンは無料ですか?
はい。「アニメーションが重要な理由」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Android Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Android Academyコースには全4レッスンが含まれています。
「アニメーションが重要な理由」で何を学びますか?
ユーザーを導き、操作を楽しませる動きを学びます。 ブラウザで直接実行するハンズオンコードでAndroid Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Android Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのAndroid Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「アニメーションが重要な理由」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このAndroid Academyレッスンでコードを書いて実行できますか?
はい。すべてのAndroid Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。