目錄
Android之MotionLayout(一),MotionLayout的基本使用
Android之MotionLayout(二),MotionScene的標簽屬性說明
Android之MotionLayout(三),用 MotionLayout 來做過渡動畫,如何使用ConstraintSet
Android之MotionLayout(四),用 MotionLayout實現(xiàn)向上拉的折疊效果
Android之MotionLayout(五),如何使用 MotionLayout的自定義屬性
Android之MotionLayout(六),如果使用Keyframes實現(xiàn)實現(xiàn)YouTube切換效果
前言
- 學習MotionLayout之前你必須了解約束布局
ConstraintLayout -
MotionLayout是ConstraintLayout的子類,在其豐富的布局功能基礎之上構(gòu)建而成
由于 MotionLayout 是基于 ConstraintLayout ,所以其中涉及到了部分關(guān)于 ConstraintLayout 的基本知識,本文按下不表,對 ConstraintLayout 不熟悉的同學,可以查看鴻洋的這篇博客。
MotionLayout簡介
MotionLayout 是一個 Google 官方出品用于制作 Android 中的過渡動畫的框架。用來它就能輕松的做出一些較為復雜的動畫效果
我們看一下效果圖:

開始使用MotionLayout
添加支持庫:
如果您使用了 AndroidX
dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1'
}
如果您沒有使用 AndroidX
dependencies {
implementation 'com.android.support.constraint:constraint-layout:2.0.0-beta1'
}
MotionLayout 最低支持到 Android 4.3(API 18),還有就是 MotionLayout 是 ConstraintLayout 2.0 添加的,因此必須確保支持庫的版本不低于 2.0。
由于 MotionLayout 類繼承自 ConstraintLayout 類,因此可以在布局中使用 MotionLayout 替換掉 ConstraintLayout
MotionLayout 與 ConstraintLayout 不同的是:
MotionLayout 需要鏈接到一個MotionScene 文件。使用 MotionLayout 的 app:layoutDescription屬性將 MotionLayout 鏈接到一個MotionScene 文件。
開始使用MotionLayout
在之前的 MotionLayout 示例中,app:layoutDescription 屬性引用一個 MotionScene。MotionScene 是一個 XML 資源文件,其中包含相應布局的所有運動描述。為了將布局信息與運動描述分開,每個 MotionLayout 都引用一個單獨的 MotionScene。請注意,MotionScene 中的定義優(yōu)先于 MotionLayout 中的任何類似定義。
MotionScene 文件描述了兩個場景間的過渡動畫,存放在 res/xml 目錄下。
要使用 MotionLayout 創(chuàng)建過渡動畫,你需要創(chuàng)建兩個 layout 布局文件來描述兩個不同場景的屬性。當從一個場景切換到另一個場景時,MotionLayout 框架會自動檢測這兩個場景中具有相同 id 的 View 的屬性差別,然后針對這些差別屬性應用過渡動畫(類似于 TransitionManger)
MotionLayout 框架支持的標準屬性:
android:visibility
android:alpha
android:elevation
android:rotation
android:rotationX
android:rotationY
android:scaleX
android:scaleY
android:translationX
android:translationY
android:translationZ
MationLayout 除了支持上面列出的標準屬性外,還支持全部的 ConstraintLayout 屬性。
我們來分三步完成線面這個例子
第 1 步:創(chuàng)建場景 1 的布局文件:
文件名 activity_scene1
<?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"
tools:showPaths="true"
app:layoutDescription="@xml/activity_motion_scene">
<ImageView
android:id="@+id/image"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/bg_circular"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.motion.widget.MotionLayout>
場景1布局效果

第 2 步:創(chuàng)建場景 2 的布局文件:
<?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"
tools:showPaths="true"
app:layoutDescription="@xml/activity_motion_scene">
<ImageView
android:id="@+id/image"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@drawable/bg_circular"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.motion.widget.MotionLayout>
場景2布局效果

說明:場景 1 與場景 2 中都有一個 id 值為 image 的 ImageView,它們的差別是:場景 1 中的 image 是水平垂直居中放置的,而場景 2 中的 image 是水平居中,垂直對齊到父布局頂部的。因此當從場景 1 切換到場景 2 時,MotionLayout 將針對 image 的位置差別自動應用位移過渡動畫。
第 3 步:創(chuàng)建 MotionScene 文件:
文件名:activity_motion_scene.xml,存放在 res/xml 目錄下
<?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:constraintSetStart="@layout/activity_main_scene1"
app:constraintSetEnd="@layout/activity_main_scene2"
app:duration="1000">
<OnClick
app:clickAction="toggle"
app:targetId="@id/image" />
</Transition>
</MotionScene>
編寫完 MotionLayout 文件后就可以直接運行程序了。點擊 image 即可進行場景切換。當進行場景切換時,MotionLayout 會自動計算出兩個場景之間的差別,然后應用相應的過渡動畫

如果你想向文章開始示意圖里顯示路徑的話 在布局文件的根目錄增加
app:showPaths="true"