MotionLayout 介紹 (第一章)

原文鏈接

MotionLayout 是 ConstrainLayout 2.0 庫中被引入的一個新類扁远,幫助安卓開發(fā)者關(guān)聯(lián)手勢和組件動畫。接下來的文章將介紹會如何在應(yīng)用中添加和使用 MotionLayout 驶鹉。

第一章將介紹MotionLayout的基礎(chǔ):

  • MotionLayout 是什么?
  • 將 ConstrainLayout 2.0 和 MotionLayout 添加到項目中
  • 如何使用 MotionLayout
  • ConstraintSets
  • MotionScene
  • 示例1: 關(guān)聯(lián)已有的布局文件
  • 處理 OnSwipe
  • 示例2: 自包含的 MotionScene
  • MotionLayout 屬性
  • 總結(jié)

你可以在這里查看示例的源碼 ConstraintLayout examples github repositor

MotionLayout 是什么榨呆?

安卓系統(tǒng)框架中已經(jīng)提供下面幾種方法在應(yīng)用中使用動畫:

這一部分將介紹 MotionLayout 與這些動畫的不同倦炒。

MotionLayout 就像它的名字一樣,首先它是一個布局刁卜,可以放置組件志电。其次它還是 ConstrainLayout 的子類,內(nèi)置豐富的功能蛔趴。

創(chuàng)建 MotionLayout 的目的是用于降低布局過渡動畫和復(fù)雜的手勢處理之間的難度挑辆,你可以認為它擁有綜合屬性動畫,TransitionManager, 和 CoordinatorLayout 的功能夺脾。

它擁有綜合屬性動畫之拨,TransitionManager, 和 CoordinatorLayout 的功能

使用 MotionLayout 你可以像 TransitionManager 一樣通過兩個布局文件描述布局的過渡動畫,但是可以使用任何屬性(不僅僅局限于 layout attribute). 還有它支持可循跡的過渡咧叭,就像 CoordinatorLayout ( 可以通過滑動即刻響應(yīng)過渡動畫 ) 。它支持通過滑動和關(guān)鍵幀自定義過渡動畫烁竭。

MotionLayout 是完全聲明式的

MotionLayout 的另外一個關(guān)鍵區(qū)別是菲茬,它是完全聲明式的。只需要 XML 文件就可以描述一個復(fù)雜的過渡動畫(如果你像通過代碼來描述動畫,系統(tǒng)提供的屬性完全可以滿足需求)婉弹。

MotionLayout 工具

我們相信這種聲明式的規(guī)范將簡化過渡動畫睬魂,同時也有助于為 Android Studio 提供更好的圖形化工具。(我們現(xiàn)在正在積極的開發(fā)這樣的工具镀赌,它現(xiàn)在還不可用氯哮。)

img

最后,作為 ConstrainLayout 2.0 的一部分商佛,它最低支持安卓 API 14喉钢,99.8%的設(shè)備都可以使用。

限制

不同于 TransitionManager 良姆,MotionLayout 只能用于他的直接子組件肠虽。

何時使用MotionLayout

我們設(shè)想到的使用 MotionLayout 的使用場景: 當(dāng)你需要移動,縮放或者動畫 實際的 UI 組件 (button玛追,title bar 等) 來提供與用戶的互動時税课。

將 ConstrainLayout 2.0 和 MotionLayout 添加到項目中

只需要將下面的代碼添加到 Gradle 文件中即可

dependencies {
    implementation 'com.android.support.constraint:constraint-layout:2.0.0-beta1'
}

如何使用 MotionLayout

MotionLayout 是 ConstrainLayout 的子類,因此你可以把它當(dāng)作一個普通的布局痊剖。 將已經(jīng)存在的 ConstrainLayout 布局轉(zhuǎn)換成 MotionLayout 布局 只需要將類名從:

<android.support.constraint.ConstraintLayout .../>

替換成

<android.support.constraint.motion.MotionLayout .../>
image

ConstrainLayout 和 MotionLayout 的主要不同是 MotionLayout 不是必須將實際描述信息包含在 XML 布局文件中韩玩。MotionLayout 通常將這些信息保存在一個單獨的 XML 文件 ( MotionScene) 中并關(guān)聯(lián)到布局文件, 通過這種方式布局文件只需要包含 View 和它們的屬性陆馁,無需包含位置信息和動畫啸如。

ConstraintSets

通常 ConstrainSet 將包含布局文件中的所有的位置信息規(guī)則; 你可以使用多個 ConstrainSet, 你可以決定將那些規(guī)則應(yīng)用到布局中氮惯,在應(yīng)用時這些 View 不會被重建叮雳,只會修改他們的位置和大小。結(jié)合 TransitionManager 使用可以很容易的創(chuàng)建 ConstrainLayout 的動畫妇汗。

MotionLayout 實際上也是源于這種思想帘不,并添加了更豐富的功能。

MotionScene

MotionLayout 的規(guī)范保存在一個單獨的 MotionScene XML文件中杨箭,該文件存儲在 res / xml 目錄中寞焙。

img

一個 MotionScene 文件可以包含動畫所需的所用內(nèi)容:

  • 包含的 ConstraintSets
  • 這些 ConstraintSet 之間的轉(zhuǎn)換(transition)
  • 關(guān)鍵幀, 事件處理

例如互婿,你可以將一個 View 從屏幕的一側(cè)拖拽到另一側(cè):

img

示例1: 關(guān)聯(lián)布局文件

你需要使用 ConstrainLayout 創(chuàng)建兩個 ConstrainSet 一個是初始位置(組件在屏幕的左面)一個是結(jié)束位置(組件在屏幕的右邊)

初始位置:

img
<?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>

結(jié)束位置:

img
<?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>

使用這兩個布局文件可以初始化兩個 ConstrainSet 捣郊,并使用他們(如果使用 TransitionManager 會有動畫的平滑過渡)。這種方式有一個問題是轉(zhuǎn)化一旦開始就不會結(jié)束慈参,你也不能告訴系統(tǒng)將轉(zhuǎn)換挺在某個位置 (你不能通過輸入事件控制轉(zhuǎn)換) 呛牲。

MotionLayout 解決了這些問題。你可以使用 MotionLayout 做同樣的事驮配,并且復(fù)用已存在的布局文件來初始化狀態(tài)娘扩。首先需要為組件創(chuàng)建一個 MotionLayout 文件(motion_01_basic.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/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"
        tools:layout_editor_absoluteX="147dp"
        tools:layout_editor_absoluteY="230dp" />

</androidx.constraintlayout.motion.widget.MotionLayout>

布局文件中引用了一個 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 設(shè)置了默認的轉(zhuǎn)換着茸,設(shè)置了開始和結(jié)束 ConstrainSet (motion_01_cl_startmotion_01_cl_end ),并為轉(zhuǎn)換設(shè)置了OnSwipe 處理琐旁。

OnSwipe handler

scene_01.xml文件中我們在 Transition 中設(shè)置了 OnSwipe 處理器涮阔。處理器通過匹配用戶的輸入事件控制轉(zhuǎn)換。

img

有一些屬性你需要了解:

touchAnchorId: 需要跟蹤的對象

touchAnchorSide: 跟蹤手指的一側(cè)(right / left / top / bottom)

dragDirection: 跟蹤手指運動的方向 ( dragRight / dragLeft / dragUp / dragDown 將決定進度值的變化0-1)

示例2: 自包含的 MotionScene

示例1展示了如何快速的創(chuàng)建一個 MotionLayout灰殴,最終使用了已存在的布局文件敬特。MotionLayout 還支持直接在 MotionScene 文件中定義 ConstraintSet 。這樣做有有以下好處:

  • 一個文件可以包含多個 ConstraintSet
  • 除了已有的功能外牺陶,還可以處理其他的屬性和自定義屬性
  • 面向未來:即將到來的 Android Studio MotionEditor 可能只支持自包含 MotionScene 文件
插值屬性

MotionScene 文件中 ConstraintSet 元素可以使用的屬性不僅包含常用的布局屬性伟阔,除了位置和邊距下面的屬性也可以在 MotionLayout 中使用:

alpha
visibility
elevation
rotation, rotation[X/Y]
translation[X/Y/Z]
scaleX/Y

讓我們?yōu)槭纠?重新創(chuàng)建一個新的自包含的 MotionScene 文件。 MotionLayout 文件除了引用了新的 scene_02.xml 和實例1中沒有區(qū)別:

<?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>

MotionScene 文件中有明顯的區(qū)別义图, Transition 的設(shè)置相同减俏,但是我們把 StartEnd直接定義在了 XML 文件中。 和普通布局文件相比主要的區(qū)別是我們沒有指定具體的組件碱工,而是把限定屬性寫在了Constraint元素中娃承。

<?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>

ConstraintSet

只需要將了解 ConstrainSet 是如何工作的,新的屬性將替換到關(guān)聯(lián)的組件上怕篷。 只需將需要替換的屬性全部包含到Constraint 中历筝。通常這會清除組件上的所用屬性并將新的屬性賦值到組件上。

MotionLayout 的屬性

在開發(fā)中你可能會用到 MotionLayout 的下列屬性:

app:layoutDescription=”reference” 指定 MotionScene XML 文件

app:applyMotionScene=”boolean” 是否應(yīng)用 MotionScene [default=true]

app:showPaths=”boolean” 是否顯示路徑 [default=false]. 記得在發(fā)布版本中關(guān)閉

app:progress=”float” 指定轉(zhuǎn)換的進度 [0-1]

app:currentState=”reference” 指定一個 ConstraintSet

總結(jié)

第一篇文章包含了 MotionLayout 的基礎(chǔ)功能廊谓, 你可以在這里查看源碼ConstraintLayout examples github repository

接下來的文章中我們將包含更多的講解:

  • 自定義屬性, 圖片變換, 關(guān)鍵幀 (part II) 中文翻譯

  • 在現(xiàn)有的布局中使用 MotionLayout (CoordinatorLayout, DrawerLayout, ViewPager) (part III) 中文翻譯

  • 關(guān)于關(guān)鍵幀的所有! (part IV)

  • MotionLayout 作為根布局

  • 嵌套 MotionLayout & 其他的組件

  • MotionLayout 和 fragments

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末梳猪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蒸痹,更是在濱河造成了極大的恐慌春弥,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叠荠,死亡現(xiàn)場離奇詭異匿沛,居然都是意外死亡,警方通過查閱死者的電腦和手機榛鼎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門逃呼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人者娱,你說我怎么就攤上這事抡笼。” “怎么了黄鳍?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵推姻,是天一觀的道長。 經(jīng)常有香客問我际起,道長拾碌,這世上最難降的妖魔是什么吐葱? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任街望,我火速辦了婚禮校翔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘灾前。我一直安慰自己防症,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布哎甲。 她就那樣靜靜地躺著蔫敲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪炭玫。 梳的紋絲不亂的頭發(fā)上奈嘿,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天,我揣著相機與錄音吞加,去河邊找鬼裙犹。 笑死,一個胖子當(dāng)著我的面吹牛衔憨,可吹牛的內(nèi)容都是我干的叶圃。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼践图,長吁一口氣:“原來是場噩夢啊……” “哼掺冠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起码党,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤德崭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后揖盘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體眉厨,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年扣讼,在試婚紗的時候發(fā)現(xiàn)自己被綠了缺猛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡椭符,死狀恐怖荔燎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情销钝,我是刑警寧澤有咨,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站蒸健,受9級特大地震影響座享,放射性物質(zhì)發(fā)生泄漏婉商。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一渣叛、第九天 我趴在偏房一處隱蔽的房頂上張望丈秩。 院中可真熱鬧,春花似錦淳衙、人聲如沸蘑秽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肠牲。三九已至,卻和暖如春靴跛,著一層夾襖步出監(jiān)牢的瞬間缀雳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工梢睛, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留肥印,地道東北人。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓扬绪,卻偏偏與公主長得像竖独,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子挤牛,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5莹痢? 答:HTML5是最新的HTML標(biāo)準。 注意:講述HT...
    kismetajun閱讀 27,486評論 1 45
  • 原文地址:http://www.android100.org/html/201606/06/241682.html...
    AFinalStone閱讀 926評論 0 1
  • 對的墓赴,是這樣竞膳。慢慢的 慢慢的抓不住青春的尾巴了。
    TKYKB閱讀 120評論 0 0
  • 之前看秦海璐和劉濤的訪談節(jié)目诫硕,很感動這種感情坦辟,我會想起阿笨以及每個階段遇見的閨蜜,但是離開家鄉(xiāng)太遠章办,很多年不見锉走。漸...
    LP橋閱讀 209評論 0 1
  • 在《4.7 Eureka Server的高可用》中,我們構(gòu)建了一個雙節(jié)點的Eureka Server集群藕届,本節(jié)我們...
    周立_itmuch閱讀 1,321評論 0 2