使用 Material Design 組件實現 Material 動效

2022-01-04 Android 開發者

收錄於話題 #Material Design 3個

近期發布的 Material 動效系統是 MDC-Android 庫 (v 1.2.0) 的一部分,它將常用的過渡效果歸納為一組簡單的模式,提供更流暢更加容易理解的用戶體驗。Material 動效目前包括四種過渡效果:

我們已經在 Android 平臺和 AndroidX 過渡系統實現了以上過渡效果,以便在 Activity、Fragment 和 View 之間切換時輕鬆使用。

Android 平臺
https://developer.android.google.cn/reference/android/transition/package-summaryAndroidX 過渡系統
https://developer.android.google.cn/reference/androidx/transition/package-summary本文會介紹上面每種模式,並解釋如何將這些模式應用到您的應用中。我將會通過在示例應用 Reply (一個簡單易用的郵件客戶端) 中實現對應的效果來說明每個步驟。Reply 應用的三個操作流程會使用到這些過渡動效: 打開郵件打開搜索頁面切換信箱
如果您不滿足於上手介紹,更希望深入源碼,請參閱 Material 動效 Codelab,按步驟上手實踐這項技術,Codelab 也提供了在 Android 上使用這些過渡效果的其他信息。容器轉換是過渡的主角,容器轉換用在將一個元素轉換為另一個元素。什麼意思呢?例如示例的一個列表展開成為了詳情頁、FAB 變形為工具欄,或 chip 擴展為了浮動的卡片。在每個場景中都有一個組件變換為另一個組件,並以動畫方式切換 "內部" 內容,同時維護一個共享的 "外部" 容器。使用容器變換,實現視圖間的動畫切換,可幫助增強它們之間的聯繫,並維持一個用戶的導航上下文。

FAB
https://material.io/components/buttons-floating-action-button

chip
https://material.io/components/chips

卡片
https://material.io/components/cards

導航上下文
https://material.io/design/navigation/navigation-transitions.html#hierarchical-transitions

在 Reply 示例中,我們在展示郵件列表的 Fragment (HomeFragment) 和郵件詳情 Fragment (EmailFragment) 間添加了容器轉換。如果您熟悉 Android 共享元素過渡,它與容器轉換的設置非常相似。HomeFragment
https://github.com/material-components/material-components-android-examples/blob/develop/Reply/app/src/main/java/com/materialstudies/reply/ui/home/HomeFragment.ktEmailFragment
https://github.com/material-components/material-components-android-examples/blob/develop/Reply/app/src/main/java/com/materialstudies/reply/ui/email/EmailFragment.ktAndroid 共享元素過渡
https://developer.android.google.cn/training/transitions/start-activity首先,確定兩個共享元素的視圖,並為每一個視圖添加過渡名稱。第一個是單個郵件列表項的卡片,我們將使用數據綁定,來確保每一個列表項都有唯一的過渡名稱。
android:transitionName="@{@string/email_card_transition_name(email.id)}"

第二個是 EmailFragment 內部的全屏卡片組件,這個組件可以設置一個靜態的過渡名稱,因為在視圖層級中只有這一個視圖。注意,兩個共享元素不需要使用相同的過渡名稱。

過渡名稱
https://developer.android.google.cn/reference/android/view/View#attr_android:transitionName

數據綁定
https://developer.android.google.cn/topic/libraries/data-binding

EmailFragment
https://github.com/material-components/material-components-android-examples/blob/develop/Reply/app/src/main/java/com/materialstudies/reply/ui/email/EmailFragment.kt

這兩個視圖會被我們的容器轉換使用。工作原理是: 它們都會被放在一個 drawable 內部,此 drawable 的邊界會被裁剪到 "容器" 中,而 "容器" 會將自己的形狀通過動畫從一個列表項轉換為詳情頁。在過渡過程中,通過傳入頁面在傳出屏幕上淡入,容器的內容 (列表項和詳情頁) 發生了交換。

現在我們已經標記了共享元素的視圖,接下來就可以創建目的地 Fragment 的 sharedElementEnterTransition,並將其設置給一個 MaterialContainerTransform 的實例。默認情況下,從詳情頁面返回時,這個 sharedElementEnterTransition 會自動反轉並播放。

sharedElementEnterTransition = MaterialContainerTransform().apply {      drawingViewId = R.id.nav_host_fragment   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()      scrimColor = Color.TRANSPARENT   setAllContainerColors(requireContext().themeColor(R.attr.colorSurface))}

有關 MaterialContainerTransform 參數的詳細信息,請參閱動效文檔:https://github.com/material-components/material-components-android/blob/master/docs/theming/Motion.md#container-transform

當一封郵件被點擊時,我們所有需要做的就是為 Fragment 事務提供開始視圖和結束視圖過渡名稱之間的映射。有了這些信息,郵箱詳情 Fragment 共享元素過渡就可以使用我們提供的 MaterialContinaerTransform 找到並在兩個視圖之間進行動畫切換。

override fun onEmailClicked(cardView: View, email: Email) {     exitTransition = MaterialElevationScale(false).apply {         duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()     }     reenterTransition = MaterialElevationScale(true).apply {           duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()     }     val emailCardDetailTransitionName = getString(R.string.email_card_detail_transition_name)     val extras = FragmentNavigatorExtras(cardView to emailCardDetailTransitionName)     val directions = HomeFragmentDirections.actionHomeFragmentToEmailFragment(email.id)     findNavController().navigate(directions, extras) }

在上面的代碼片段中,我們也為傳出頁郵件列表 Fragment 設置了 exit 和 reenter 的過渡效果。Material 組件提供了兩個過渡輔助: Hold 和 MaterialElevationScale,以平滑地為將要被替換的 Fragment 設置動畫。除了褪色 (Fade),MaterialElevationScale 還會在郵件列表頁退出時,對其進行縮放,並在重新進入郵件列表時縮放回來。Hold 僅僅是簡單地保留郵件列表。如果沒有設置退出時的過渡,我們的郵件列表會被立刻刪除並從視圖中消失。

Hold
https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/transition/Hold.java

MaterialElevationScale
https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/transition/MaterialElevationScale.java

如果我們在這個時候運行代碼,從詳情頁導航返回到郵件列表頁,則返回過渡不會執行。這是因為當過渡開始時,郵件列表的適配器還未被填充,過渡系統找不到與過渡名稱對應的兩個視圖。幸運的是,有兩個簡單方法可供我們使用: postponeEnterTransition 和 startPostponedEnterTransition。這兩個方法允許我們延遲過渡,直到我們知道我們的共享元素已經被布局,並且可以被過渡系統發現。在 Reply 應用中,我們可以使用以下代碼延遲過渡,直到我們確定 RecyclerView 適配器已被填充,列表項已和過渡名稱綁定:

postponeEnterTransition()view.doOnPreDraw { startPostponedEnterTransition() }

在您自己的應用中,您可能需要嘗試這兩種方法,以根據您填充 UI 的方式和時間,來找到合適的時間開始延遲過渡。如果您發現您的返回動畫沒有執行,可能是在共享元素就緒之前開始了過渡。

接下來進入我們的搜索頁面。

共享軸模式用於有空間和導航關係的 UI 元素之間的過渡。在 Reply 應用中,打開搜索頁面會將用戶帶到郵件列表頂部的新頁面。為了介紹這個三維模型,我們可以在郵件列表 (HomeFragment) 和搜索頁面 (SearchFragment) 之間使用共享 z 軸過渡。

HomeFragment
https://github.com/material-components/material-components-android-examples/blob/develop/Reply/app/src/main/java/com/materialstudies/reply/ui/home/HomeFragment.kt

SearchFragment
https://github.com/material-components/material-components-android-examples/blob/develop/Reply/app/src/main/java/com/materialstudies/reply/ui/search/SearchFragment.kt

共享軸過渡會在操作兩個目標的同時創建最終的、編排過的過渡效果。這意味著 "成對" 的過渡會一起運行去創建連續的定向的動畫。對 Fragment 來說,這成對的過渡包括:

FragmentA 的 exitTransition 和 FragmentB 的 enterTransitionFragmentA 的 reenterTransition 和 FragmentB 的 returnTransitionMaterialSharedAxis 是實現了共享軸模式的類,它接收 forward 屬性來控制方向性的概念。在每一個過渡配對中,forward 必須被設置為相同的值,以便正確地協調這對動畫。如需了解更多關於共享軸方向性的詳細信息,請查閱動效文檔:

https://material.io/design/motion/the-motion-system.html

MaterialSharedAxis
https://github.com/material-components/material-components-android/blob/master/lib/java/com/google/android/material/transition/MaterialSharedAxis.java

在 Reply 應用中,這是我們為當前的 Fragment (HomeFragment) 建立退出和重入過渡的方法。

currentNavigationFragment?.apply {   exitTransition = MaterialSharedAxis(      MaterialSharedAxis.Z,        true   ).apply {      duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()   }   reenterTransition = MaterialSharedAxis(      MaterialSharedAxis.Z,        false   ).apply {       duration =resources.getInteger(R.integer.reply_motion_duration_large).toLong()   }}

HomeFragment
https://github.com/material-components/material-components-android-examples/blob/develop/Reply/app/src/main/java/com/materialstudies/reply/ui/home/HomeFragment.kt

在我們目的 fragment (SearchFragment) 中,我們建立進入和返回的過渡。

enterTransition = MaterialSharedAxis(   MaterialSharedAxis.Z,    /* forward= */ true).apply {   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()}returnTransition = MaterialSharedAxis(   MaterialSharedAxis.Z,    /* forward= */ false).apply {   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()}

SearchFragment
https://github.com/material-components/material-components-android-examples/blob/develop/Reply/app/src/main/java/com/materialstudies/reply/ui/search/SearchFragment.kt

注意: 當前 Fragment 的退出過渡和搜索 Fragment 的進入過渡使用相同的 forward 值 - true,當前 Fragment 的重入過渡和搜索 Fragment 的返回過渡也是如此。

接下來,默認情況下,過渡會在場景根層次結構內的所有子視圖上運行,這意味著一個共享軸過渡會應用於郵件列表上的每一封郵件以及搜索頁面的每一個子視圖。如果您想要 "傳播" 或者 "錯開" 動畫,這是一個非常好的功能,但是由於我們需要對每個 Fragment 的根作為整體進行動畫處理,我們需要在郵件列表的 RecyclerView 和我們的搜索頁面的根 view group 設置 android:transitionGroup="true"

錯開
https://material.io/archive/guidelines/motion/choreography.html#choreography-creation

郵件列表的 RecyclerView
https://github.com/material-components/material-components-android-examples/blob/develop/Reply/app/src/main/res/layout/fragment_home.xml#L18

搜索頁面的根 view group
https://github.com/material-components/material-components-android-examples/blob/develop/Reply/app/src/main/res/layout/fragment_search.xml#L17

這樣,我們就在進出搜索頁面時有了一個漂亮的共享 z 軸過渡!共享軸是一個非常靈活的過渡,可以應用於許多不同的場景,從頁面過渡到智能回複選擇,再到進入或者垂直的步驟流程。您已經配置好了設置,還可以嘗試使用 MaterialSharedAxis 的 axis 參數來了解其他軸動畫是什麼樣子。

我們要介紹的最後一個模式是淡入淡出模式。淡入淡出可用於在沒有強關係的 UI 元素間過渡。當在兩個信箱之間過渡時,我們不希望用戶認為他們已經發送的郵件和他們的收件箱在導航上相關。由於每個信箱是一個頂級的目的地,淡入淡出是一個合適的選擇。在 Reply 應用中,我們將用不同的電子郵件列表 (帶有新參數的 HomeFragment) 替換電子郵件列表 (HomeFragment)。

由於 MaterialFadeThrough 沒有方向性,所以設置起來更加簡單。我們只需要為傳出 Fragment 設置一個退出過渡,為傳入 Fragment 設置一個進入過渡。

currentNavigationFragment?.apply {   exitTransition = MaterialFadeThrough().apply {       duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()   }}

enterTransition = MaterialFadeThrough().apply {   duration = resources.getInteger(R.integer.reply_motion_duration_large).toLong()}

在郵件列表的 RecyclerView 上設置 android:transitionGroup="true" 的需求同樣適用於這裡,但是我們已經在共享軸配置的步驟中解決了這個問題。郵件列表的 RecyclerView
https://github.com/material-components/material-components-android-examples/blob/develop/Reply/app/src/main/res/layout/fragment_home.xml#L25

以上就是淡入淡出過渡!您可以在自己項目有趣的地方來使用淡入淡出模式,比如: 底部導航欄的切換、列表項的交換,或替換一個工具欄菜單。

本文簡要介紹了 Android 的 Material 動效系統。通過使用該系統所提供的模式,您可以在自定義動效時,做很多事情,使動效成為品牌體驗的一部分。本文我們看到了 Fragment 的過渡,但動效系統也可用於 Activity 甚至 View 間的過渡。查看完整的動效規範文檔,獲得更多啟發,以便思考哪些地方可提高您應用的核心體驗,或在一些小的地方增加額外的樂趣。

Material 動效開發文檔: 您可以在 Material Android 動效文檔找到許多關於在 Activity 和 View 之間進行動畫的自定義選項和建議。

https://github.com/material-components/material-components-android/blob/master/docs/theming/Motion.md

Material 動效 Codelab: 一個完整的分步的開發者教程,內容涉及如何在 Reply 應用中添加 Material 動效。

https://codelabs.developers.google.com/codelabs/material-motion-android/#0

Android Google 雲盤: 您可以在 Android Google 雲盤應用中看到正在運行的動效系統。點擊文件夾、打開搜索、在底部導航間切換,這些都用到了 MDC-Android 的過渡效果。

https://play.google.com/store/apps/details?id=com.google.android.apps.docs

 點擊屏末 閱讀原文 | 即刻了解更多 Material 動效相關內容

👆點擊獲取 "開發者的日常" 表情包

相關焦點

  • 推薦開發者使用 Material Design 組件
    您在設計視覺和導航模式時應該遵循 Material Design 規範…您可以使用 Material Design Components (MDC) 組件庫來實現這一目的。本文將列出使用 MDC 的優勢,從而說明我們推薦使用它的原因。
  • Material design無需照搬Google
    最近,我們決定替換一下我們常備的郵件app原型,換成更迷人、跟上時代的東西——其中考慮採用了Google的material design原則。我們要確堅持material design基於觸摸、用動效表達意義、大膽地表達意圖的核心原則,但不能完全複製Google Now或是Inbox。我們想在此從兩給方面分享構建這套界面的收穫:其一,分享我們關於material風格的思考和設計。其二,分享界面本身——你可以從文末獲取到。
  • Material Design 系列之 TextInputLayout 開發詳解
    二、TextInputLayout 使用詳解1、基本使用布局文件中只需要在 EditText 外層包裹一層 TextInputLayout 布局即可<com.google.android.material.textfield.TextInputLayout    android:id="@+id/userInputLayout
  • 新版MATERIAL DESIGN 官方動效指南
    在Material design的世界中,動效用一種優雅、流動的方式來描述空間關係、功能、和意向。動效可以向我們展示一個App 是如何構成和用途。動效可以做到:不同視圖之間的焦點引導。材料設計的動效轉場是沿著一個弧線的。3. 可察覺的材料設計的動效是可以被周圍環境察覺的,包括用戶和周圍其他的元素。
  • 28個頂級的React UI組件庫,請查收!
    React 的另一大優點是組件。開發者可以使用組件將 UI 拆分成獨立、可復用的部分。本文將介紹 20 多個優秀的 React 組件,幫助開發者迅速地應用它們。React Material-UI 是一組實現了谷歌 Material Design 設計語言的 React 組件。
  • 【第1724期】用React Hooks與Web Animation API實現動效組件
    正文從這開始~~動效組件一個體驗良好的動效完全可以吸引用戶的更多停留,以一種通用的方式從側面提升業務的轉化效果,某些特定場景下,動畫所能起到的作用甚至可以與業務的目標並駕齊驅。對於PC端產品來說,Web頁面動畫的價值主要增加體驗舒適度、增加web頁面活力、以及展示頁面的層級關係或者提供反饋。
  • 2019年Material Design獎獲獎應用公布/Adobe Creative Cloud桌面端重大改版:打造一站式商城
    在新版本中微軟放棄了原有的圓角設計,轉而使用了方形設計。本次更新可以自動下載,或者跳轉到「關於Microsoft Edge」進行手動檢查更新。來源:cnbeta.com/articles/tech/898093.htm5 .
  • 剛剛,谷歌對 Material Design 做了7個重大更新
    從材質調色板中選擇顏色,使用單一顏色自動生成10個顏色值的色調,使用全局顏色更改自動填充symbols。1.2 設置形狀選擇你的形狀和邊角風格,從彎曲或切割的角落樣式中進行選擇,並自動將更改應用於您的材質組件,在材質庫中的組件中使用對稱和非對稱形狀進行播放 - 同時保留在材質設計指南中
  • ...ESPRESTO Fluffy material Code Geass 叛逆的魯魯修 紅月卡蓮...
    萬代 眼鏡廠 ESPRESTO Fluffy material Code Geass 叛逆的魯魯修 紅月卡蓮 兔女郎 時間:2020-07-03 15:41:25   來源:   責任編輯:冥王星
  • 萬代 眼鏡廠 ESPRESTO Fluffy material Code Geass 叛逆的魯魯修...
    萬代 眼鏡廠 ESPRESTO Fluffy material Code Geass 叛逆的魯魯修 CC 兔女郎 時間:2020-06-17 22:19:22   來源:   責任編輯:冥王星
  • Sika·Design | 敬畏生命,敬重自然,我們才會走得長遠
    「 When I started in the furniture business many years ago, I wasintrigued by the rattan material’s designpossibilities.
  • 2021年你應該知道的9個網頁組件庫
    根據定義,所有web組件都是可互操作的,可以很好地與其他組件協作。自定義組件和小部件建立在網頁組件標準之上,可以跨現代瀏覽器工作,並且可以與任何與HTML一起工作的JavaScript庫或框架一起使用。那麼現在網上有哪些現成的網頁組件庫科研使用呢?下面為大家提供了9個不錯的組件庫,希望能對你有所幫助。1.
  • 分享 | 動效落地神器Lottie
    如今很多 UI 設計師不是正在做動效,就正在學著做動效。動效現在已經無處不在了。動效怎麼實現呢?大家都知道,設計師負責設計動效,而把動效實現在產品上就得勞煩開發了。動效實現的還原度就取決於設計師與開發之間相互博弈的過程。
  • UI設計中顏色使用的10條原則
    我們可以留意到:許多公司在其品牌營銷活動中都使用色彩作為一種策略。許多快餐店的品牌都使用紅色和黃色,這是因為紅色引發刺激,食慾,飢餓的效果,並引起人們的注意,而黃色則給人帶來幸福和友善的感覺。6. 有限的顏色通過限制在應用程式中使用過多顏色,可以使應用顏色區域中的內容受到更多關注,例如界面中的文本,圖像以及按鈕等單個元素。
  • 2016年GOOD DESIGN AWARD設計師交流盛會上海站即將在漫生快活舉辦
    Thedesign ofPRIMUS 200 epitomizes the product values and commitment tothecustomers:Simplicity, Ease of Use, and Quality.
  • 使用 vue 實現一個電子籤名組件
    本文轉載於 SegmentFault 社區作者:我的小熊不見了
  • 榮譽|新冶組設計斬獲K-DESIGN AWARD全球大獎
    this case, the designer used the concept of space capsule base to create the entire architectural appearance, and because of local characteristics, add national treasure panda entertainment’s IP symbol material