前言
前幾天在逛公衆號的時候偶然看到了關於MotionLayout的文章,效果確實非常的神奇,所以在網上查看了相關的資料,可能是比較新的東西,所以資料上介紹的並不是很全,就自己嘗試了一下,寫一個筆記記錄一下心得。本文是爲了快速入門,所以不會介紹的很詳細,需要詳細瞭解的可以去看看網上的其他資料。
正文
MotionLayout是ConstraintLayout的子類,ConstraintLayout已經推出很久了,相信大家都多多少少了解一些,這裏就不做介紹了。MotionLayout可以直接在xml中綁定動畫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/motion_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/scene1">
<ImageView
android:id="@+id/image"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@mipmap/ic_launcher_round" />
</androidx.constraintlayout.motion.widget.MotionLayout>
我什麼佈局參數都沒有設置,效果就是一個圖片顯示在左上角。
MotionScene
如果想要ImageView動起來,我們需要MotionScene,可以簡單的理解爲常用的補間動畫的根節點,他還包含了非常豐富的子節點,我們一一瞭解一下:
ConstraintSet
通俗的講可以理解爲一個屬性集合,可以定義多個,每一個集合可以設置id,通過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">
<ConstraintSet android:id="@+id/start">
<Constraint
android:id="@+id/image"
android:layout_width="48dp"
android:layout_height="48dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint
android:id="@+id/image"
android:layout_width="48dp"
android:layout_height="48dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</ConstraintSet>
</MotionScene>
上面的示例代碼中定義了兩個屬性集合:start和end。分別把image這個View設置不同的位置。ConstraintSet中的屬性優先級最高,會覆蓋掉xml中的佈局參數,所以我們可以把公共佈局參數寫在xml中,需要變化的佈局參數寫在ConstraintSet中。
Transition
我們已經定義了好了開始狀態和結束狀態,接下來就是要讓他動起來,這裏我們需要使用Transition。
<Transition
app:constraintSetEnd="@id/end"
app:constraintSetStart="@id/start"
app:duration="1000">
<OnClick
app:clickAction="toggle"
app:targetId="@id/image" />
</Transition>
設置開始的狀態是start,結束的狀態爲end,時間爲1000毫秒,觸發動畫的條件是OnClick(點擊),點擊的控件的id爲image。
除了點擊事件,還可以設置滑動:
<OnSwip app:dragDirection="dragRight""/>
OnSwipe表示手指滑動,dragDirection表示手指滑動的方向,即動畫的開始的方向。有一些資料還用了touchAnchorId和touchAnchorSide,經過測試發現這兩個屬性對動畫沒有什麼影響,可能是預留的屬性,還沒有具體實現。
現在我們已經完成了一個非常簡單的平移動畫。
KeyFrameSet
如果我們想要在某一幀進行控制,就需要使用KeyFrameSet,他還包含了四個子標籤:KeyPosition,KeyAttribute,KeyTimeCycle,KeyCycle。
KeyPosition
KeyPosition表示一個關鍵的位置,例如我們滑動到一半的時候,我們希望是在屏幕的中間:
<KeyPosition
app:framePosition="50"
app:keyPositionType="parentRelative"
app:motionTarget="@id/image"
app:percentY="0.5" />
framePosition:關鍵的位置,範圍爲0到100,可以理解爲動畫的百分比,50就是動畫的一半。
motionTarget:動畫的控件的id。
keyPositionType:計算位置的類型,parentRelative相對父佈局。
percentY:範圍爲0到1,高度的百分比,他是和keyPositionType一起使用的。
MotionScene會自動幫助我們讓動畫變得順滑,而不是突然跳到我們指定的位置。
KeyAttribute
KeyAttribute表示關鍵的屬性,用來描述View本身的屬性的變化,例如縮放,旋轉等等,讓動畫更加的豐富。
<KeyAttribute
android:rotation="-360"
android:scaleX="2"
android:scaleY="2"
app:framePosition="50"
app:motionTarget="@id/image" />
KeyTimeCycle
KeyTimeCycle表示循環動畫,他會跟一直顯示在View上,不會隨着動畫的變化而消失,例如下面的代碼,會給View增加一個左右來回晃動的動畫:
<KeyTimeCycle app:motionTarget="@id/image"
android:rotation="50"
app:waveShape="sin"
app:wavePeriod="1" />
KeyCycle
KeyCycle和KeyTimeCycle有一些類似,他們的屬性完全相同,他表示動畫過程中的循環動畫,但是KeyCycle的優先級比KeyTimeCycle要高,如果設置KeyCycle,KeyTimeCycle不會生效。
<KeyCycle app:motionTarget="@id/image"
app:framePosition="30"
android:rotation="50"
app:waveShape="sin"
app:wavePeriod="1" />
例如上面的代碼頁實現在動畫中實現左右晃動的效果,並且可以設置動畫的開始位置。
StateSet
從字面意思理解是一個狀態集合,但是從源碼上,我沒有看到這個的屬性的使用場景,可能是爲了之後豐富動畫切換效果預留的。
總結
我們已經簡單瞭解了MotionLayout動畫的基本用法,寫一個簡單的補間動畫已經綽綽有餘,更高級的用法就需要慢慢學習了,希望本文能幫助大家快速入門MotionLayout。