Androidプログラミング

【Android】簡単にレイアウトをアニメーションさせる方法【MotionLayout】

AndroidのMotionLayout(レイアウトアニメーション)の紹介記事のアイキャッチ Android

Androidアプリにおいて、レイアウトをアニメーションさせる方法を紹介します。一瞬で画面レイアウトが変化するとユーザの認識が追い付かない場合があるので、アニメーションを使用することで「何がどのように変化・移動したか」を認識しやすくすることができるようになります。MotionLayoutというレイアウトタイプを使用します。

スポンサーリンク

MotionLayoutを使いアニメーションさせるための前準備

MotionLayoutを使うために以下を、build.gradle(app)に追記します。

dependencies {
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
}

これでConstraintLayout依存関係を追加できました。
(MotionLayoutはConstrainLayoutのサブクラス)

スポンサーリンク

MotionLayoutを使いアニメーションを実装させる流れ

以下の手順で実装できます。

  • build.gradle(app)のdependencies{}を追記
  • xmlファイルにMotionLayoutを記載
  • アニメーションを制御するためのMotionSceneファイルを作成(場所:res>xmlフォルダの中)
  • MotionSceneファイルを記載
  • アニメーションのトリガーを記載(今回はMainActivityのKotlinファイルに記載)
スポンサーリンク

レイアウトをアニメーションさせるサンプル

今回は以下のようなサンプルを作成しました。

サンプルアプリの動作の様子

ボタンを押すと、Boolean型の変数(onoff_flg)のtrue/falseが反転する。その反転に応じてTextViewのサイズを変化させる(もちろんアニメーション付きで)。

サンプルはfindViewByIdではなく、Bindingを使用しています(分からない方は以下記事を参照ください)。

XMLファイル(メインのLayoutファイル)

ボタンとMotionLayoutを配置します。
MotlinLayoutの中には今回アニメーションで変化させるTextViewを配置します。

<!-- フラグ操作用のボタン -->
<Button
    android:id="@+id/btnONOFF"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:text="ON/OFF" />

<!-- モーションに関するレイアウト -->
<androidx.constraintlayout.motion.widget.MotionLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/motionLayout"
    android:layout_width="300dp"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:background="#0f0"
    app:layoutDescription="@xml/activity_main_scene">

    <TextView
        android:id="@+id/tvTarget"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:background="#ff0"
        android:text="Sample Text" />

</androidx.constraintlayout.motion.widget.MotionLayout>

MotionLayoutを記載するとAndroidStudioの補完機能で「波線」が表示されることがあります。その修正に従うと自動でMotionSceneファイルが生成されます。

XMLファイル(MotionSceneファイル)

<Transition />には遷移に関する情報(アニメーションの開始/終了のid、全体時間)を記載します。

<ConstraintSet />はstart、endの2種類を記載します。アニメーション対象はidで指定します。

<?xml version="1.0" encoding="utf-8"?>
<MotionScene
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- 遷移に関する情報 -->
    <Transition
        app:constraintSetEnd="@id/end"
        app:constraintSetStart="@+id/start"
        app:duration="1000" />

    <!-- アニメーション開始の状態 -->
    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/tvTarget"
            android:layout_height="20dp" />
    </ConstraintSet>
    
    <!-- アニメーション終了の状態 -->
    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/tvTarget"
            android:layout_height="200dp"
            android:layout_width="match_parent"/>
    </ConstraintSet>
</MotionScene>

メインアクティビティ(Kotlinファイル)

setアクセサをON/OFFフラグに実装します。

これによりフラグが変化(反転)するたびにset()が呼ばれるのでそこにアニメーション処理を記載しています(12,14行目)。

19行目以下はただのボタンを押すとonoffFlg(Boolean)が反転するプログラムです。

class MainActivity : AppCompatActivity() {

    private lateinit var binding : ActivityMainBinding

    // ON/OFFフラグ
    var onoffFlg:Boolean = false
        set(value: Boolean){
            field = value

            //値に応じてアニメーションを実行する
            if(field){
                binding.motionLayout.transitionToEnd()
            }else{
                binding.motionLayout.transitionToStart()
            }
        }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        val view = binding.root
        setContentView(view)

        //クラスを用いたクリックリスナー-------
        //インスタンス生成
        val sampleListener = SampleListener()
        //ボタンにリスナ追加
        binding.btnONOFF.setOnClickListener(sampleListener)
    }

    //リスナクラス
    private inner class SampleListener : View.OnClickListener{
        //private lateinit var binding : ActivityMainBinding

        override fun onClick(v: View) {
            when(v.id){
                binding.btnONOFF.id ->{
                    // ボタンが押される度にtrue/falseを反転
                    onoffFlg = !onoffFlg
                }
            }
        }
    }
}
スポンサーリンク

さいごに

Androidでのレイアウトをアニメーションさせる方法を紹介しました。

ファイルが増えるとややこしく感じますが、やっていることはシンプルで上手くできているなぁと感じました。

以下Android関連記事です。

コメント

タイトルとURLをコピーしました