【正社員】還元率83%【フリーランス】マージン一律5万円で案件をご紹介させていただきます。 詳細はこちら

【Android】<Kotlin>Compose Animations APIの「animate*AsState」関数を使ってモダンなアニメーションを実装する方法!

【Android】<Kotlin>Compose Animations APIを活用したモダンなアニメーションの実装方法を徹底解説!
すだ

みなさまこんにちは〜!
メモリアインクのすだです。

本日は、
KotlinのCompose Animations APIの「animate*AsState」関数を使って
アプリ画面にモダンなアニメーションを実装する方法を、
実際のコードを利用して徹底解説していきます!

この記事を読んでわかること…
・Compose Animations APIとは?
・Compose Animations APIを使用したアニメーションの実装方法

目次

環境

  • Kotlin (ver 1.9.0)
  • Android Studio (Giraffe | 2022.3.1 Patch 3)

Compose Animations APIとは?

Compose Animations APIは、アニメーションを簡単かつ柔軟に作成するためのツールです。
モダンUIフレームワークであるJetpack Composeに統合されており、その中でも特にスムーズなアニメーションを宣言的に記述できます。

以下のような特徴があります。▼

  1. 宣言的UIに完全対応
  2. 状態に基づいたアニメーションの自動制御
  3. シンプルな構文で強力なカスタマイズが可能

また、今回はCompose Animations APIの特定の関数をご紹介しますが
Jetpack Composeは他にも数多くの便利なAPIを提供しています。
用途に応じて ぜひ調べて使ってみてください!

animate*AsStateとは?

animate*AsStateは、Compose Animations APIの一機能で
状態に応じてアニメーションを適用する最も基本的な方法です。

以下のように 型に応じた関数が様々に用意されています。▼

関数名対象の型用途
animateDpAsStateDpサイズや間隔、マージンのアニメーション
animateFloatAsStateFloat回転角度、透明度、スケールのアニメーション
animateColorAsStateColor背景色やテキスト色のアニメーション
animateIntAsStateInt数値やピクセルサイズのアニメーション
animateOffsetAsStateOffset要素の移動や位置変更のアニメーション
animateRectAsStateRect矩形領域のアニメーション
animateSizeAsStateSize要素全体の幅と高さのアニメーション
animateIntOffsetAsStateIntOffset整数型の座標位置のアニメーション
animateIntSizeAsStateIntSize整数型の幅と高さのアニメーション
val size by animateIntSizeAsState(IntSize(300, 300))

UIの要件に応じて最適な関数を選択してください!

例として、いくつか実装してみましょう!

animate*AsStateを使った様々な実装

animateDpAsState: ボタンをクリックするとサイズが変化する実装

@Composable
fun SimpleDpAnimationExample() {
    var isExpanded by remember { mutableStateOf(false) }
    val size by animateDpAsState(targetValue = if (isExpanded) 200.dp else 100.dp)

    Box(
        modifier = Modifier
            .size(size)
            .background(Color.Blue)
            .clickable { isExpanded = !isExpanded }
    )
}

@ComposableJetpack Compose における Composable関数 を示すためのアノテーションです。
このアノテーションが付いた関数は、Jetpack ComposeのUIを構築するために使用されます。

3行目:

  • isExpanded
    • ボックスが「拡大状態かどうか」を管理するフラグです。
  • remember
    • Composeがこの状態をリメンバーし、再コンポーズ時も状態を保持します。
      初期状態は false(縮小状態)です。

4行目:

  • animateDpAsState
    • 状態が変化するたびに、指定した値 (targetValue) に向けてスムーズにアニメーションします。
    • isExpandedtrue のときは 200.dpfalse のときは 100.dp にアニメーションという実装です。

6行目~:

  • Box
    • 背景色を指定した四角形を描画するコンポーネントです。
  • Modifier.size(size)
    • アニメーションで変化するサイズをここで適用します。
  • Modifier.clickable { isExpanded = !isExpanded }
    • ボックスをクリックするたびに isExpanded を反転させます。
      その結果として、サイズが縮小 (100.dp) または拡大 (200.dp) に切り替わります。

ビルドしてボタンを操作すると以下のようになります。

【Android】<Kotlin>Compose Animations APIの「animate*AsState」関数を使ってモダンなアニメーションを実装する方法!

animateFloatAsState: ボタンをクリックすると回転する実装

@Composable
fun SimpleWidthAnimation() {
    var isRotated by remember { mutableStateOf(false) }

    // 2秒間で回転
    val rotationAngle by animateFloatAsState(
        targetValue = if (isRotated) 360f else 0f,
        animationSpec = tween(
            durationMillis = 2000, // アニメーションの時間(ミリ秒単位)
            easing = LinearEasing // 等速で回転
        )
    )

    Box(
        modifier = Modifier
            .size(100.dp)
            .graphicsLayer(rotationZ = rotationAngle)
            .background(Color.Blue)
            .clickable {
                isRotated = !isRotated
            }
    )
}

3行目:

  • isRotated
    • 回転するかどうかの状態を管理するフラグ。初期値は false(回転していない状態)です。

6行目~:

  • animateFloatAsState
    • 状態(isRotated)に応じて、回転角度(rotationAngle)をアニメーションで変化させます。
    • ターゲット値:
      • true の場合: 360度(1回転)。
      • false の場合: 0度(元の位置)。
    • animationSpec: アニメーションの動き方を設定します。
      • tween で 2000ミリ秒(2秒)かけて回転を行う。
      • LinearEasing を指定し、回転速度を一定にする。

15行目~:

  • graphicsLayer(rotationZ = rotationAngle)
    • ボックスの Z軸(画面に対して垂直方向) を基準に回転させます。
    • rotationAngle の値に応じて回転します。
  • clickable
    • タップ操作で isRotated の値を切り替えます。
      (状態が切り替わるたびに、アニメーションが発火)

ビルドしてボタンを操作すると以下のようになります。

【Android】<Kotlin>Compose Animations APIの「animate*AsState」関数を使ってモダンなアニメーションを実装する方法!

(gifにするとなかなかわかりづらいですが、実際はきちんと回転しています)

animateIntAsState: ボタンをクリックすると幅が変化する実装

@Composable
fun SimpleWidthAnimation() {
    var isExpanded by remember { mutableStateOf(false) }
    val width by animateIntAsState(targetValue = if (isExpanded) 300 else 100)

    Box(
        modifier = Modifier
            .height(100.dp)
            .width(width.dp)
            .background(Color.Green)
            .clickable { isExpanded = !isExpanded }
    )
}

3行目:

  • isExpanded
    • ボックスが「拡大状態かどうか」を管理するフラグです。
  • remember
    • Composeがこの状態をリメンバーし、再コンポーズ時も状態を保持します。
      初期状態は false(縮小状態)です。

4行目:

  • animateIntAsState
    • isExpanded に基づいて、ボックスの幅(width)をアニメーションします。
    • true の場合は幅が 300dp に、false の場合は幅が 100dp になります。
    • 幅の変化がスムーズにアニメーションされます。

7行目~:

  • Modifier.width(width.dp)
    • animateIntAsState で計算された幅を適用します。
  • Modifier.clickable { isExpanded = !isExpanded }
    • ボックスをクリックするたびに isExpanded を反転させ、アニメーションをトリガーします。

ビルドしてボタンを操作すると以下のようになります。

【Android】<Kotlin>Compose Animations APIの「animate*AsState」関数を使ってモダンなアニメーションを実装する方法!

まとめ

おつかれさまでした。いかがでしたでしょうか!

Compose Animations APIのanimate*AsState関数を活用すれば、シンプルなアニメーションから高度なカスタムアニメーションまで簡単に実現できます。

ぜひアプリ画面の実装に、役立ててくださいね〜!

すだ

技術者としてのキャリアパスを次のレベルへと進めたい皆様、
未経験からIT・Webエンジニアを目指すなら【ユニゾンキャリア】
を通じて、
自分の市場価値をさらに向上させてみませんか?

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

弊社テックブログをご愛読いただきありがとうございます。
当テックブログを運用している株式会社メモリアインクは、
【正社員】還元率83%
【フリーランス】マージン一律5万円で案件のご紹介
と、エンジニアの皆様に分かりやすい形で稼げる仕組みを構築し提供させていただいております。

コメント

コメントする

目次