アニメーションを使ってビューを移動する

Compose の方法を試す
Jetpack Compose は、Android で推奨される UI ツールキットです。Compose でアニメーションを使用する方法について学習します。

画面上のオブジェクトの位置の変更が必要になることがよくあります。その理由は、ユーザーの操作やバックグラウンド処理によるものです。オブジェクトの位置を瞬間的に更新し、ある領域にあるオブジェクトが突然消えて別の領域に突然現れるようにするのではなく、アニメーションを使用して、開始位置から終了位置に移動させることをおすすめします。

Android で画面上のビュー オブジェクトの位置を変更する方法の一つは、ObjectAnimator を使用することです。オブジェクトを配置する終了位置と、アニメーションの持続時間を指定します。時間インターポレータを使用して、アニメーションの加速または減速を制御することもできます。

ObjectAnimator を使用してビューの位置を変更する

ObjectAnimator API を使用すると、指定した持続時間に基づいてビューのプロパティを変更できます。これには、アニメーション化する属性のタイプに応じて ObjectAnimator のインスタンスを作成する静的メソッドが含まれています。画面上のビューの位置を変更するときは、translationX 属性と translationY 属性を使用します。

画面の左から 100 ピクセルの位置に 2 秒でビューを移動する ObjectAnimator の例を次に示します。

Kotlin

ObjectAnimator.ofFloat(view, "translationX", 100f).apply {
    duration = 2000
    start()
}

Java

ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f);
animation.setDuration(2000);
animation.start();

この例では、変換値を float 型にする必要があるため、ObjectAnimator.ofFloat() メソッドを使用しています。1 番目のパラメータは、アニメーション化するビューを示しています。2 番目のパラメータは、アニメーション化するプロパティを示しています。ビューを水平方向に移動する必要があるため、translationX プロパティを使用しています。最後のパラメータは、アニメーションの終了値を示しています。この例の値 100 は、画面の左から何ピクセル分離れた位置にあることを示します。

次のメソッドでは、アニメーションの時間をミリ秒単位で指定します。この例の場合、アニメーションの実行時間は 2 秒間(2,000 ミリ秒)になります。

最後のメソッドにより、アニメーションが実行され、画面上のビューの位置が更新されます。

ObjectAnimator の使用方法については、ObjectAnimator を使用してアニメーション化するをご覧ください。

曲線モーションを追加する

ObjectAnimator は便利ですが、デフォルトでは、開始点と終了点を結ぶ直線に沿ってビューの位置が変更されます。マテリアル デザインは、画面上のオブジェクトの空間的な動きとアニメーションのタイミングに関しても曲線をベースとしています。曲線モーションを使用することで、アニメーションの魅力を高めつつ、マテリアル デザインとしての質も高めることができます。

独自の経路を定義する

ObjectAnimator クラスには、パスとともに一度に 2 つ以上のプロパティを使用して座標をアニメーション化できるコンストラクタがあります。たとえば、次のアニメーターでは、Path オブジェクトを使用して、ビューの X プロパティと Y プロパティをアニメーション化しています。

Kotlin

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    val path = Path().apply {
        arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true)
    }
    val animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path).apply {
        duration = 2000
        start()
    }
} else {
    // Create animator without using curved path
}

Java

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  Path path = new Path();
  path.arcTo(0f, 0f, 1000f, 1000f, 270f, -180f, true);
  ObjectAnimator animator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
  animator.setDuration(2000);
  animator.start();
} else {
  // Create animator without using curved path
}

これにより、次のような弧を描くアニメーションを作成できます。

図 1. 曲線のパス アニメーション。

Interpolator はイージング カーブの実装です。イージング カーブのコンセプトについて詳しくは、マテリアル デザインのドキュメントをご覧ください。Interpolator は、アニメーションの特定の値を時間の関数として計算する方法を定義します。マテリアル デザイン仕様では、次の 3 つの基本的な曲線の XML リソースが用意されています。

  • @interpolator/fast_out_linear_in.xml
  • @interpolator/fast_out_slow_in.xml
  • @interpolator/linear_out_slow_in.xml

PathInterpolator を使用する

PathInterpolator クラスは、Android 5.0(API 21)で導入されたインターポレーターです。このクラスは、ベジェ曲線または Path オブジェクトをベースとします。マテリアル デザインのイージング ドキュメントに記載されている Android の例では、PathInterpolator を使用しています。

PathInterpolator には、さまざまな種類のベジェ曲線に基づくコンストラクタがあります。すべてのベジェ曲線の始点と終点は、それぞれ (0,0)(1,1) に固定されています。他のコンストラクタ引数は、作成するベジェ曲線のタイプによって異なります。

たとえば、2 次ベジェ曲線の場合は、1 つの制御点の X 座標と Y 座標のみが必要です。

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    PathInterpolator(0.67f, 0.33f)
} else {
    LinearInterpolator()
}

Java

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  myInterpolator = new PathInterpolator(0.67f, 0.33f);
} else {
  myInterpolator = new LinearInterpolator();
}

これにより、開始時に急速に加速し、終了に近づくにつれて減速するイージング カーブが生成されます。

3 次ベジェ コンストラクタも同様に始点と終点が固定されていますが、次の 2 つのコントロール ポイントが必要です。

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f)
} else {
    LinearInterpolator()
}

Java

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  myInterpolator = new PathInterpolator(0.5f, 0.7f, 0.1f, 1.0f);
} else {
  myInterpolator = new LinearInterpolator();
}

これは、マテリアル デザインの強調減速の減衰曲線の実装です。

より詳細に制御するために、任意の Path を使用して曲線を定義できます。

Kotlin

val myInterpolator = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  val path = Path().apply {
    moveTo(0.0f, 0.0f)
    cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f)
  }
  PathInterpolator(path)
} else {
  LinearInterpolator()
}

Java

Interpolator myInterpolator = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  Path path = new Path();
  path.moveTo(0.0f, 0.0f);
  path.cubicTo(0.5f, 0.7f, 0.1f, 1.0f, 1.0f, 1.0f);
  myInterpolator = new PathInterpolator(path);
} else {
  myInterpolator = new LinearInterpolator();
}

これにより、3 次ベジェ曲線のサンプルと同じイージング曲線が生成されますが、代わりに Path が使用されます。

経路インターポレーターは、XML リソースとして定義することもできます。

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:controlX1="0.5"
    android:controlY1="0.7"
    android:controlX2="0.1f"
    android:controlY2="1.0f"/>

PathInterpolator オブジェクトを作成したら、Animator.setInterpolator() メソッドに渡します。Animator は、インターポレーターを使用して、開始時のタイミングやパス曲線を決定します。

Kotlin

val animation = ObjectAnimator.ofFloat(view, "translationX", 100f).apply {
    interpolator = myInterpolator
    start()
}

Java

ObjectAnimator animation = ObjectAnimator.ofFloat(view, "translationX", 100f);
animation.setInterpolator(myInterpolator);
animation.start();