mcpField
C
compose-animations

compose-animations

github.com/chrisbanesデザイン・UI1.1k1.9k 回インストール1 日前に更新
リポジトリ

compose-animations について

Compose 開発者向けに、動きの要件とライフサイクルに応じたアニメーション API の選択を支援するスキルです。コンテンツの識別、テスト、フレーム単位の性能上の注意点も扱います。

主な機能

  1. 01要件に応じた Compose API の選択
  2. 02状態アニメーションとジェスチャーの区別
  3. 03ライフサイクルとコンテンツ識別の確認
  4. 04性能とテスト上の注意点

活用シーン

  1. 01UI の表示・非表示アニメーションの選択
  2. 02共通状態に基づく値の連携
  3. 03AnimatedContent の切り替えのレビュー
  4. 04フレーム単位のレイアウトや描画負荷の診断

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/chrisbanes/skills --skill compose-animations

インストール後、Claude Code で/compose-animationsを入力して読み込まれたか確認します。

同梱ファイルreferences/animated-content.md

詳細

Compose:アニメーション

基本原則

動きとそのライフサイクルを表現できる、最もシンプルな API を選びます。

手順

  1. 目的を特定します。サブツリーの表示・非表示、単一の値のアニメーション、1 つの状態に基づく複数の値の連動、コンテンツのサイズ変更、コンテンツの切り替え、またはユーザー操作に応じた動きの処理です。
  2. 表から該当する API を選びます。ターゲット状態 API を優先し、ジェスチャー、中断、または命令的な制御が必要な場合に限り Animatable を使います。
  3. ライフサイクルを確認します。アルファアニメーションではコンテンツはコンポジションに残りますが、AnimatedVisibility では終了後に取り除かれます。アンマウントが必要な場合はフェードを使わないでください。
  4. AnimatedContent では、コンテンツラムダのターゲットから描画し、視覚的な同一性がペイロードの等価性と異なる場合に限り contentKey を選びます。異なるアイテム間を切り替える場合は、ターゲット値を同一性として維持する(デフォルト)か、安定したアイテム ID をキーにします。異なるアイテムを共通の表示状態キーや分岐キーにまとめないでください。レビューでは、外側のターゲット状態をキャプチャする描画式を明示し、その箇所ではラムダのターゲットを使うよう推奨します。テストで遷移の同一性を証明する必要がある場合は、遷移中に終了側と開始側のコンテンツを確認します。遷移完了後の表示先だけを確認すると、同一性が共有されている不具合を見逃します。状態保持の詳細については、AnimatedContent の同一性を参照してください。
  5. アニメーション対象の State がフレームごとに変化する場合は、レイアウトまたは描画ブロックの修飾子で使用します。詳細な診断はCompose のパフォーマンスを参照してください。
  6. この機能が制御する遷移先の切り替えには Navigation Compose の遷移を使い、アートベースの動きには専用ライブラリを使います。
  7. API、ライフサイクル、コンテンツの同一性が UI に合致し、よりシンプルな API がなく、関連する動作も検証されたら完了です。

API の選択

必要なもの推奨
表示・非表示の開始・終了動作を伴うサブツリーの表示・非表示AnimatedVisibility
状態に追従する単一の値animate*AsState
1 つのブール値、列挙型、または sealed 状態に追従する複数の値rememberTransition と子アニメーション
子要素のサイズ変更Modifier.animateContentSize()
異なるコンポーザブルツリーで 1 つの領域を埋めるAnimatedContent、または単純なケースでは Crossfade
ドラッグ、フリング、中断、または命令的な制御Animatable

デフォルトの動きが適切でない場合は AnimationSpec を使います。複数のアニメーションをツールで識別できるようにするには、個別の label を設定します。

val width by animateDpAsState(
    targetValue = if (expanded) 200.dp else 56.dp,
    animationSpec = spring(dampingRatio = 0.7f),
    label = "fabWidth",
)

同期を保つ必要がある値には、独立した複数の animate*AsState 呼び出しではなく、1 つの遷移に定義します。

val transition = rememberTransition(targetState = phase, label = "phase")
val alpha by transition.animateFloat(label = "alpha") { target ->
    if (target == Phase.Visible) 1f else 0f
}
val offset by transition.animateDp(label = "offset") { target ->
    if (target == Phase.Visible) 0.dp else 24.dp
}

アニメーション付きの塗りつぶしでは、色が毎フレーム更新される場合、値を受け取る形式の background よりも drawBehind { drawRect(color.value) } を優先します。API の選択に迷った場合は、公式のアニメーション API の選び方ガイドを参照してください。繰り返しサイクルには rememberInfiniteTransition を、シーク可能な進行状況やテストで制御する進行状況には SeekableTransitionState を使います。

このスキルを使わない場合

コメント