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関連記事です。








コメント