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関連記事です。
コメント