ConstrainLayout2.0之MotionLayout
黑白
發(fā)布于 云南 2018-12-26 · 2.9w瀏覽 1贊

前言

MotionLayout?是一個(gè)在 ConstraintLayout 2.0 版本庫中新增的類,用于幫助 Android 開發(fā)者,在他們的 App 中,管理手勢以及動(dòng)畫組件。


在這個(gè)系列文章我們將揭露,你如何添加這個(gè)庫到你的 App 里,以及如何運(yùn)用 MotionLayout 的概念和特性來編寫程序。

在這個(gè)系列文章的 第一部分 我將揭露 MotionLayout 的基礎(chǔ):

  • MotionLayout 因何而生?

  • 添加 ConstraintLayout 2.0 以及 MotionLayout 到你的工程

  • 運(yùn)用 MotionLayout

  • ConstraintSets

  • MotionScene

  • 第一個(gè)例子:

  • OnSwipe handler

  • 第二個(gè)例子:

  • MotionLayout 的屬性

  • 小結(jié)

你也可以在 ?ConstraintLayout examples github repository 或者 這里 找到這些例子的源碼。

MotionLayout 因何而生?

Android 框架已經(jīng)提供了好幾種在 App 里添加動(dòng)畫的方式:

下面將揭示 MotionLayout 和上面這些已有方案的不同。

MotionLayout,從它的名字就可以知道,首先它是一個(gè)布局控件,可以讓你安置你的元素。事實(shí)上它是 ConstraintLayout 的子類,進(jìn)而在它的基礎(chǔ)上構(gòu)建了更強(qiáng)大的布局功能。

MotionLayout 作為 連接布局過度和復(fù)雜的手勢操作之間的橋梁 而生。你可以把它當(dāng)做介于屬性動(dòng)畫框架、TransitionManager 和 CoordinatorLayout 之間的功能集合。

它可以讓你描述兩個(gè)布局的過渡動(dòng)畫(類似 TransitionManager 那樣),而且還可以描述任何屬性動(dòng)畫(不僅僅是布局屬性)。( 譯者注:這里的 “描述”,指的就是用 xml 表示 ) 此外,它內(nèi)置支持聯(lián)動(dòng)(原文:seekable transitions),正如 CoordinatorLayout(它可以通過觸摸事件,和任意一點(diǎn)產(chǎn)生過渡動(dòng)畫的聯(lián)動(dòng))。它支持觸摸操作和關(guān)鍵幀,可以讓開發(fā)者更容易根據(jù)自身需要自定義過渡動(dòng)畫。

MotionLayout 是完全聲明式的。

除了上面提到的,MotionLayout 另一個(gè)關(guān)鍵的不同點(diǎn)在于它是完全聲明式的——你可以完全在 XML 中描述一個(gè)復(fù)雜的過渡動(dòng)畫——無需任何代碼。如果你需要使用代碼表達(dá)移動(dòng)手勢,現(xiàn)有的屬性動(dòng)畫框架已經(jīng)提供了一個(gè)很好的方式實(shí)現(xiàn)它。(譯者注:言下之意,要用代碼實(shí)現(xiàn)動(dòng)畫,那就用回屬性動(dòng)畫吧)

MotionLayout 輔助工具

我們確實(shí)認(rèn)為,對(duì)聲明式移動(dòng)規(guī)格的關(guān)注將簡化創(chuàng)建動(dòng)畫,由此在 Android Studio 中提供了很好的圖像化工具。

由于我們正在開發(fā)這個(gè)工具,目前它是不可用的。一旦這個(gè)庫到了 stable 或者 beta 版本,這個(gè)工具就可以用了。



最后,作為 ConstraintLayout 2.0 的一部分,它可以作為一個(gè)支持庫,向下兼容到 API 級(jí)別 18,也就是JellyBean MR2(譯者注:就是我們通常說的 Android 4.3):這意味著它支持當(dāng)下 95% 的 Android 設(shè)備,可以查看 Android 系統(tǒng)實(shí)時(shí)市場占比 (譯者注:需科學(xué)上網(wǎng))

限制

MotionLayout 將僅僅為它的直接子視圖提供上述功能——這點(diǎn)正好和 TransitionManger 不一樣,TransitionManager 不僅還可以作用于內(nèi)嵌布局,還可以作用于 Activity 場景動(dòng)畫。

何時(shí)使用它?

當(dāng)動(dòng)畫 UI 元素和用戶產(chǎn)生交互時(shí),我們就可以使用 MotionLayout

認(rèn)識(shí)清楚動(dòng)畫是為什么目標(biāo)服務(wù)這是至關(guān)重要的——在你的應(yīng)用中,它不應(yīng)該是簡單的一個(gè)無端特效;它應(yīng)該能夠幫助用戶理解你的 App 正在做什么。Material Design 原則之 Understanding motion很好的介紹了這些理念。

有一個(gè)動(dòng)畫類僅僅要處理演示預(yù)先的內(nèi)容,用戶不會(huì)或者不需要直接和內(nèi)容發(fā)生交互。一段視頻,一個(gè)動(dòng)圖,或者以有限的方式比如動(dòng)畫矢量或者 lottie 通常就屬于這一范疇。MotionLayout 不會(huì)特別的嘗試處理這類動(dòng)畫(但是你當(dāng)然可以把他們包含在一個(gè) MotionLayout 中)

添加 MotionLayout 到你的工程

簡單的通過添加 ConstraintLayout 2.0 到你的 Gradle 配置文件就可以了。

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

運(yùn)用 MotionLayout

MotionLayout 是 ConstraintLayout 的一個(gè)子類——這樣,你可以把它視為一個(gè)普通的布局。現(xiàn)有的 ConstraintLayout 轉(zhuǎn)換為 MotionLayout 是很容易的,只要像下面這樣替換類名:

改成


ConstraintLayout 和 MotionLayout 最主要的差異在于 XML 級(jí)別(_譯者注:使用 MotionLayout 就可以知道,在 xml 中它有一個(gè) app:layoutDescription 屬性),MotionLayout 的子視圖布局屬性,并不一定要包含在布局文件中。

當(dāng)然,MotionLayout 通常子視圖布局屬性放到一個(gè)分開的 xml 文件中(這就是一個(gè) MotionScene)然后引用它,而且定義在此處的子視圖布局屬性將優(yōu)先于布局文件的子視圖布局屬性。

這種方式,布局文件僅僅只包含自視圖和它們的屬性,而不包括它們的位置和運(yùn)動(dòng)。


ConstraintSets

ConstraintSet 大體的思想是,它們封裝所有的定位規(guī)則為你的布局;并且你能夠使用多個(gè) ConstraintSet,然后你可以決定這一組規(guī)則立即運(yùn)用于你的布局,而不需要重新創(chuàng)建你的視圖——僅僅只是改變它們的位置或者尺寸。

結(jié)合 TransitionManager(若無法科學(xué)上網(wǎng)可參考這里),這個(gè)提供了一個(gè)相對(duì)容易的方式使用 ConstraintLayout 創(chuàng)建動(dòng)畫,正如上面視頻講述的那樣。

MotionLayout 本質(zhì)上是構(gòu)建于這些思想之上,同時(shí)擴(kuò)展這些概念進(jìn)一步發(fā)展。

MotionScene

如之前提到的那樣,和通常的布局控件不同,MotionLayout 的一些規(guī)格保存在另外一個(gè) XML 文件中,它就是一個(gè) MotionScene,存放于的 res/xml 資源目錄下。



一個(gè) MotionScene 文件能夠包含所有下面指定的動(dòng)畫:

  • 使用 ConstraintSets

  • 這些 ConstraintSets 之間的過度動(dòng)畫

  • 關(guān)鍵幀,觸摸操作,等等。

例如,讓我們嘗試實(shí)現(xiàn),使用你的手指能夠拖拽移動(dòng)一個(gè)視圖,從屏幕的一端到另一端。



示例01:引用存在的布局

使用 ConstraintLayout,你將要?jiǎng)?chuàng)建兩個(gè) ConstraintSet —— 一個(gè)是第一個(gè)位置(位于控件在屏幕的左邊),一個(gè)第二個(gè)位置(位于控件在屏幕的右邊)。

然后使用 TransitionManager 可以實(shí)現(xiàn)動(dòng)畫。但是使用這種方式有一個(gè)問題,那就是,一旦過渡動(dòng)畫開始,它就無法中斷。也就是說,你不能夠讓系統(tǒng)跳轉(zhuǎn)到過渡動(dòng)畫指定的時(shí)間點(diǎn)——意味著你不能通過用戶輸入驅(qū)動(dòng)過渡動(dòng)畫。

譯者注:上面兩段翻譯本人閑寫得太啰嗦了,就粗略的翻譯了原文,作者的基本意圖就是引出下面使用 MotionLayout 比上面說的原有 ConstraintSet 方式更簡單有效,且使用類似 TransitionManger 的方式并不能夠?qū)崿F(xiàn)用戶驅(qū)動(dòng)的動(dòng)畫。

MotionLayout 就解決了所有的這些問題。下面展示你如何實(shí)現(xiàn)同樣的動(dòng)畫,只要重用這些已經(jīng)存在的布局,來初始化兩個(gè)狀態(tài)。
首先,我們將創(chuàng)建一個(gè) MotionLayout 文件為我們的控件:




????

注意,這個(gè)布局文件引用了一個(gè) MotionScene 文件 —— scene_01

下面就是 scene_01:




????
????????
????

scene_01 指定默認(rèn)的過渡動(dòng)畫,通過指定起始的 ConstraintSet(如上所示的:motion_01_cl_start 和 motion_01_cl_end) 。注意除此之外,我們還指定了一個(gè) OnSwipe 來處理這個(gè)過渡動(dòng)畫。

好!就這樣,你就能實(shí)現(xiàn)上面提到的動(dòng)畫了。

OnSwipe handler

回到上面提到的 scene_01.xml 文件,我們指定了一個(gè) OnSwipe 處理者,被包含在 Transition 里。這個(gè)處理者的角色是讓你驅(qū)動(dòng)這個(gè) Transition,通過匹配你的手指運(yùn)動(dòng)。



有些參數(shù)需要你來設(shè)置:

  • touchAnchorId: 我們需要追蹤的對(duì)象(這個(gè)例子中就是,@+id/button)

  • touchAnchorSide: 需要追蹤你手指運(yùn)動(dòng)的對(duì)象邊界(right/left/top/bottom)

  • dragDirection: 我們正追蹤的運(yùn)動(dòng)方向(dragRight / dragLeft / dragUp / dragDown 可以被設(shè)置通過定義進(jìn)度值,從 0 到 1)



黑白
2333
瀏覽 2.9w
1
相關(guān)推薦
最新評(píng)論
贊過的人 1
評(píng)論加載中...

暫無評(píng)論,快來評(píng)論吧!