MotionLayout:一個可以直接寫動畫的ConstraintLayout

前言

前幾天在逛公衆號的時候偶然看到了關於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。

發佈了116 篇原創文章 · 獲贊 59 · 訪問量 25萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章