MotionLayout介紹

MotionLayout

本文是對Introduction to MotionLayout的翻譯,本身可能翻譯的有點很差,歡迎你們批評指正。侵權刪。php

MotionLayout是一個在ConstraintLayout2.0版本庫的時候添加的一個新的類,能夠幫助開發者處理一些動畫。android

Android framework已經提供瞭如此多的方式來幫咱們在應用中添加動畫,app

  • Drawable矢量圖
  • 屬性動畫
  • CoordinatorLayout
  • LayoutTransition animations
  • 利用TransitionManager的Layout transitions

那麼MotionLayout與它們有什麼不一樣的地方?ide

  • MotionLayout是ConstraintLayout的一個子類,受益於ConstraintLayout豐富的特性
  • MotionLayout讓layout佈局元素可以在動畫過渡期間也可以響應用戶的UI交互

何時使用它?

當想要對與用戶有直接交互的UI元素作動畫時。佈局

什麼是對與用戶有着直接交互的UI元素?就是用戶的點擊,滑動等動做。gradle

添加MotionLayout到你的項目

dependencies {
    implementation 'com.android.support.constraint:constraint-layout:2.0.0-alpha2'
}
複製代碼

使用MotionLayout

MotionLayout是ConstraintLayout的子類。要想已有的ConstraintLayout變成MotionLayout只須要在具體的xml中,將:動畫

<android.support.constraint.ConstraintLayout .../>
複製代碼

改爲google

<android.support.constraint.motion.MotionLayout .../>
複製代碼

MotionLayout動畫的具體的描述文件並無包含在定義MotionLayout的layout文件中,而是定義在了一個單獨的xml文件(一個MotionScene文件)。spa

MotionScene

就如同以前所說,描述MotionLayout的動畫的具體信息被定義在了一個單獨的xml文件,MotionScene,一般存儲在res/xml目錄下翻譯

如圖所述,一個MotionScene一般包含以下的內容

  • 所使用的ConstraintSets
  • 所使用的ConstraintSets的transition(過渡階段)
  • keyframes(關鍵幀)

就像下面的例子,咱們經過使用手指拖動一個簡單的view從屏幕的一端滑動至另外一端,如何作到呢?

實現1:引用已有的layouts

一個指向初始的layout(view在屏幕左端),一個指向結束的layout(view在屏幕的右端),咱們須要定義兩個layout

view在左端的layout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent">

    <View android:id="@+id/button" android:background="@color/colorAccent" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" android:text="Button" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>
複製代碼

view在右端的layout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent">

    <View android:id="@+id/button" android:background="@color/colorAccent" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" android:text="Button" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>
複製代碼

而後定義一個MotionLayout文件

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.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" app:layoutDescription="@xml/scene_01" tools:showPaths="true">

    <View android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:background="@color/colorAccent" android:text="Button" />

</android.support.constraint.motion.MotionLayout>
複製代碼

注意這個layout文件指向了一個MotionScene文件---scene_01

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:motion="http://schemas.android.com/apk/res-auto">

    <Transition motion:constraintSetStart="@layout/motion_01_cl_start" motion:constraintSetEnd="@layout/motion_01_cl_end" motion:duration="1000">
        <OnSwipe motion:touchAnchorId="@+id/button" motion:touchAnchorSide="right" motion:dragDirection="dragRight" />
    </Transition>

</MotionScene>
複製代碼

scene_01經過指定開始和結束的ConstraintSet(motion_01_cl_startmotion_01_cl_end,規定了過渡動畫。注意,咱們指定了OnSwipe標籤在transition中

OnSwipe標籤

scene_01.xml文件中,咱們指定了一個OnSwipe標籤,在一個Transition標籤中,做用是依據咱們的手指的動做,來讓動畫發生。

OnSwipe的具體的各類屬性

touchAnchorId:咱們想要作動畫的object對象,(這裏是@+id/button

touchAnchorSide:object的邊,(right/left/top/bottom)

dragDirection:咱們所想要追蹤的手指動做的方向(dragRight/dragLeft/dragUp/dragDown)

實現2:將ConstraintSets直接定義在MotionScene中

第一種實現方式重用了layout(基於ConstraintLayout)

MotionLayout一樣支持直接在MotionScene中定義ConstraintSets,這帶來了以下優點:

  • 只須要一個文件,就能夠包括全部的ConstraintSets
  • 方便處理attributes
  • 將來Android Studio將只支持這種將ConstraintSets直接定義在MotionScene中的方式

讓咱們將ConstraintSets直接定義在MotionScene中,達到和實現1同樣的效果

咱們定義一個與實現1中同樣的MotionLayout文件,只須要引用scene_02.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/motionLayout" app:layoutDescription="@xml/scene_02" android:layout_width="match_parent" android:layout_height="match_parent">

    <View android:id="@+id/button" android:background="@color/colorAccent" android:layout_width="64dp" android:layout_height="64dp" android:text="Button" />

</android.support.constraint.motion.MotionLayout>
複製代碼

scene_02.xml中,Transition標籤內部是一致的,區別在於咱們直接將startend的Constrait定義在了文件中。並由一個ConstraintSet標籤包含着。

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android" xmlns:motion="http://schemas.android.com/apk/res-auto">

    <Transition motion:constraintSetStart="@+id/start" motion:constraintSetEnd="@+id/end" motion:duration="1000">
        <OnSwipe motion:touchAnchorId="@+id/button" motion:touchAnchorSide="right" motion:dragDirection="dragRight" />
    </Transition>

    <ConstraintSet android:id="@+id/start">
        <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginStart="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintStart_toStartOf="parent" motion:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint android:id="@+id/button" android:layout_width="64dp" android:layout_height="64dp" android:layout_marginEnd="8dp" motion:layout_constraintBottom_toBottomOf="parent" motion:layout_constraintEnd_toEndOf="parent" motion:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>

</MotionScene>
複製代碼

能夠被自動插值的屬性(Interpolated Attributes)

在Constraint標籤中除了能夠定義元素的位置以外,還能夠定義一些其餘的屬性,MotionLayout將自動地爲這些屬性生成中間的過渡狀態,也就是插值。

alpha

visibility

elevation

rotation,rotation[x / y]

translation[x / y / z]

scaleX / Y

相似於下面的形式

<Constraint android:id="@id/content" android:layout_width="0dp" android:layout_height="match_parent" motion:layout_constraintWidth_default="percent" motion:layout_constraintWidth_percent="1" android:scaleX="0.8" android:scaleY="0.8" motion:layout_constraintLeft_toRightOf="@+id/button" motion:layout_constraintTop_toTopOf="parent"/>
複製代碼

MotionLayout能夠定義的屬性

MotionLayout提供了一些屬性

app:layoutDescription="reference",指向一個MotionScene XML文件

app:applyMotionScene="boolean"是否使用MotionScene,默認爲true

app:showPaths="boolean"展現motion 路徑,默認爲false,app正式發佈的時候要記得關閉

app:pregress="float"明確指定中間進度,區間在0到1

app:currentState="reference"強制一個特定的ConstraintSet

這篇文章只是MotionLayout的基礎的功能的一個介紹,MotionLayout可以實現的功能遠不止如此。

相關文章
相關標籤/搜索