MotionLayoutのKeyCycleを使ってアニメーションを実装してみた


この記事は、and factory Advent Calendar 202023日目の記事です。
昨日は@cpp0302さんの「GoのDIライブラリ google/wire でモックを使う場合のベストプラクティス」でした!

試したこと

  • クリックすると画像が揺れるアニメーションをMotionLayoutのKeyCycleを使って実装してみました
    • 参考にしたアニメーション

環境

  • Android Studio 4.0.1
  • constraintlayout:2.1.0-alpha1

MotionLayoutとは

  • アニメーションを構築するためのConstraintLayoutのサブクラス。2.0で追加されました。
  • 宣言的にアニメーションを実装することができる
    • 複雑な遷移をXMLで記述できる
  • ユーザーが操作するUI要素をアニメーション化するときにMotionLayoutを使用する

KeyCycleとは

  • アニメーション中のポストレイアウトプロパティの位置に関する振動を制御する

実装

xml.activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/motionLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@xml/motion_key_cycle_01"
    tools:showPaths="true">

    <ImageView
        android:id="@+id/button"
        android:layout_width="120dp"
        android:layout_height="120dp"
        android:src="@drawable/alpaca"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.motion.widget.MotionLayout>
xml.motion_key_cycle_01.xml
<KeyFrameSet>
    <KeyCycle
        android:rotationX="20"
        app:framePosition="10"
        app:motionTarget="@+id/button"
        app:waveOffset="0"
        app:wavePeriod="1"
        app:waveShape="sin" />
    <KeyCycle
        android:rotationY="20"
        app:framePosition="30"
        app:motionTarget="@+id/button"
        app:waveOffset="0"
        app:wavePeriod="1"
        app:waveShape="sin" />
    <KeyCycle
        android:rotationX="20"
        app:framePosition="50"
        app:motionTarget="@+id/button"
        app:waveOffset="1"
        app:wavePeriod="1"
        app:waveShape="sin" />
    <KeyCycle
        android:rotationY="20"
        app:framePosition="70"
        app:motionTarget="@+id/button"
        app:waveOffset="1"
        app:wavePeriod="1"
        app:waveShape="sin" />
</KeyFrameSet>

表示

終わりに

  • 少し動作がぎこちない箇所はありますが、同じようなアニメーションが再現できたのかなと思います
    • waveOffsetの効果はまだよくわかっていないところです。
  • KeyCycleを使うと揺らぎ?のあるアニメーションをXMLで実装できるようでした
  • クリックする度に異なるアニメーションが再生されることがありました。毎回、同じアニメーションを再生する場合は、最初の状態に戻す制御が別で必要そうです
  • github

参考ページ