再不遷移到Material Design Components 就out啦

sydMobile 發表於 2020-09-15

翻譯自國外文件加自己理解 原文

我們最近宣佈了 Material Design Components(MDC)1.1.0 ,這是一個庫更新,為您的 Android 應用程式帶來了 Material Theming 、新的元件、深色主題和其他令人興奮的功能。

MDC取代了設計支援庫。本指南將向您展示如何遷移程式碼庫,以便您可以使用新的屬性,樣式和小部件。

精簡的主題示例

本指南使用了精簡的應用程式來演示遷移過程。它使用AppCompat主題,設計支援庫中的小部件(包括具有自定義背景的按鈕)以及需要遷移的各種其他元素。我們將從使用傳統AppCompat模板的應用程式主題開始:

<style name="Theme.App" parent="Theme.AppCompat.*">
    <item name="colorPrimary">@color/navy_700</item>
    <item name="colorPrimaryDark">@color/navy_900</item>
    <item name="colorAccent">@color/green_300</item>
</style>

再不遷移到Material Design Components 就out啦

使用 AppCompatDesign Support Library 的 APP

Support Library 遷移到 JetPack

在使用MDC之前,您需要從支援庫遷移到Android Jetpack。Jetpack使用新的androidx.*名稱空間,並將以前的支援庫程式包拆分為單獨維護的語義版本化的庫,從而提供部分功能的新庫。MDC是使用AndroidX庫構建的,因此必須進行遷移。

要遷移到 AndroidX ,建議您遵循官方開發人員文件。 Android Studio中的 重構 > 遷移到 AndroidX 工具會將您的 Design Support Library 依賴重構成 MDC

更新到 MDC

首先要將build.gradle 依賴中

com.android.support:design:28.0.0 修改成 com.google.android.material:material:1.0.0

更改主題

需要將 app 的主題修改成 Material Components 主題的子類

<style name = "Theme.App" parent = "Theme.AppCompat.*" 修改成

<style name = "Theme.App" parent = "Theme.MaterialComponents.">

MDC 主題中有樣式和 AppCompat 一一對應,在大多數情況下,只需要簡單的將 AppCompat 替換成 MaterialComponents 就可以了

AppCompat theme MDC-Android theme
Theme.AppCompat Theme.MaterialComponents
Theme.AppCompat.NoActionBar Theme.MaterialComponents.NoActionBar
Theme.AppCompat.Dialog.* Theme.MaterialComponents.Dialog.*
Theme.AppCompat.DialogWhenLarge Theme.MaterialComponents.DialogWhenLarge
Theme.AppCompat.Light Theme.MaterialComponents.Light
Theme.AppCompat.Light.DarkActionBar Theme.MaterialComponents.Light.DarkActionBar
Theme.AppCompat.Light.NoActionBar Theme.MaterialComponents.Light.NoActionBar
Theme.AppCompat.Light.Dialog.* Theme.MaterialComponents.Light.Dialog.*
Theme.AppCompat.Light.DialogWhenLarge Theme.MaterialComponents.Light.DialogWhenLarge
Theme.AppCompat.DayNight Theme.MaterialComponents.DayNight
Theme.AppCompat.DayNight.DarkActionBar Theme.MaterialComponents.DayNight.DarkActionBar
Theme.AppCompat.DayNight.NoActionBar Theme.MaterialComponents.DayNight.NoActionBar
Theme.AppCompat.DayNight.Dialog.* Theme.MaterialComponents.DayNight.Dialog.*
Theme.AppCompat.DayNight.DialogWhenLarge Theme.MaterialComponents.DayNight.DialogWhenLarge
AppCompat theme overlay MDC-Android theme overlay
ThemeOverlay.AppCompat ThemeOverlay.MaterialComponents
ThemeOverlay.AppCompat.Light ThemeOverlay.MaterialComponents.Light
ThemeOverlay.AppCompat.Dark ThemeOverlay.MaterialComponents.Dark
ThemeOverlay.AppCompat.*.ActionBar ThemeOverlay.MaterialComponents.*.ActionBar.*
ThemeOverlay.AppCompat.Dialog.* ThemeOverlay.MaterialComponents.Dialog.*
N/A ThemeOverlay.MaterialComponents.*.BottomSheetDialog
N/A ThemeOverlay.MaterialComponents.MaterialAlertDialog.*
N/A ThemeOverlay.MaterialComponents.MaterialCalendar.*
N/A ThemeOverlay.MaterialComponents.Toolbar.*

例子更新

再不遷移到Material Design Components 就out啦

Button 改變

Design 庫到 MDC ,樣式變成 Theme.MaterialComponents.* 後有了一些變化。拿 Button 來舉例,Button失去了自定義背景。現在 Button 有了一個綠色的強調色並且字型間的間距變大了。

再不遷移到Material Design Components 就out啦

那麼為什麼會這樣呢?我們先來看一下佈局

<Button
    android:id="@+id/containedButton"
    // 這是自定義的某種顏色的背景
    android:background="@drawable/bg_button_gradient"
    android:textColor="@android:color/white"
    ... />
<Button
    android:id="@+id/textButton"
    style=”?attr/borderlessButtonStyle”
    ... />

之所以出現這種情況是因為,在填充佈局的時候,會自動將我們佈局中的普通控制元件替換成 MDC 控制元件。

和 AppCompat 一樣,MDC 會在填充的時候用 MDC 等效的控制元件來替換某些原始控制元件。這樣就可以釋出新功能和錯誤修正了,而不必將所有宣告都換成新的型別。這是通過 MaterialComponentsViewInflater 來完成的,它屬於 AppCompatViewInflater 的子類。

對映關係:

Framework widget AppCompat widget (replaced by AppCompatViewInflater) MDC-Android widget (replaced by MaterialComponentsViewInflater)
Button AppCompatButton MaterialButton
CheckBox AppCompatCheckBox MaterialCheckBox
RadioButton AppCompatRadioButton MaterialRadioButton
TextView AppCompatTextView MaterialTextView
AutoCompleteTextView AppCompatAutoCompleteTextView MaterialAutoCompleteTextView

注意:MDC 1.0.0 中只有 Button 控制元件被替換了。

我們例子中如果是 Theme.AppCompat.* 的主題,那麼就會把 ButtonAppCompatButton 來替換。現在把主題修改成 Theme.MaterialComponents.* ,那麼就會把 Button 替換成 MaterialButton ,會有預設的 style

AppCompatButton 不同的是 MaterialButton 不支援自定義背景。到 1.2.0-alpha06 版本開始支援。使用 Shape 可以進行變通。下面章節會詳細介紹。

更新到 MDC 1.1.0

從 1.0.0 到 1.1.0 有了很多新變化:

  • 完整的 Material Theming
  • Dark Theme 支援
  • Android 10 手勢導航支援
  • 新元件:擴充套件 FAB、date picker、badges、toggle buttons
  • 無障礙功能提升、bug 修復等等

implementation ‘com.google.android.material:material:1.1.0’

一些出乎意料的改變和普通問題

MDC 1.1.0更改了一些預設的小部件樣式,以更好地符合“材料設計”準則。但是,升級後,您可能會注意到某些控制元件顏色和其他屬性的某些意外更改。

再不遷移到Material Design Components 就out啦

在上面的示例中,按鈕發生了變化、文字和圖示的顏色發生了變化。FAB 現在變成了藍綠色,並且文字欄位看起來完全不同。不用擔心。我們的當前主題中可能是丟失了一些重要的 MDC 屬性,同時有一些重要的 AppCompat 或者原有屬性(android:xxx)不再需要。下面我們通過一些常見的遷移方案來了解一下這些問題

文字欄位改變

在 MDC 中,文字欄位預設樣式發生了改變。改進版本是經過使用者調查研究的。

再不遷移到Material Design Components 就out啦

我們建議您使用這個版本,來提高可用性和可配置項性。但是我們意識到這可能並不適合您的品牌和設計系統。

要恢復為舊的文字欄位可以在佈局中新增樣式

<com.google.android.material.textfield.TextInputLayout
    ...
+    style="@style/Widget.Design.TextInputLayout">
    ...
</com.google.android.material.textfield.TextInputLayout>

或者你也可以在主題中給所有的文字設定預設樣式

<style name="Theme.App" parent="Theme.MaterialComponents.*">
    ...
+    <item name=”textInputStyle”>@style/Widget.App.TextInputLayout</item>
</style>

+<style name=”Widget.App.TextInputLayout” parent=”Widget.Design.TextInputLayout”>
+    <!-- Custom attrs -->
+</style>

再不遷移到Material Design Components 就out啦
再不遷移到Material Design Components 就out啦

更喜愛 MDC 樣式和控制元件

如上所述,先前支援庫的風格已經變成了 MDC 的一部分。在大多數的情況下,我們都可以通過 Widget.MaterialComponents.* 來替換 Widget.Design.* 樣式。並且還啟用了新的屬性,雖然可以不使用,但是我們建議還是採用新的 MDC 樣式!

建議使用 MDC 元件來替換AppCompat 或者 MaterialButton (如果有的話)這些元件預設情況下使用更新後的材料設計指南。並且支援啟用 Material Theming 和其他功能。

下面這幾種情況應該考慮

  • 在佈局中寫的控制元件如果有對應的 MDC 控制元件的話,直接使用 MDC 控制元件
  • 任何的風格,預設風格和預設風格屬性應該改變成 MDC 版本
  • 在程式設計中或者自定義類的父級類使用的任何控制元件都應該為 MDC 版本。

完整 控制元件和樣式對映表

MDC-Android widget (moved from Design Support Library) Design Support Library default style MDC-Android default style Default style attr
AppBarLayout Widget.Design.AppBarLayout Widget.MaterialComponents.AppBarLayout.* appBarLayoutStyle
BottomNavigationView Widget.Design.BottomNavigationView Widget.MaterialComponents.BottomNavigationView bottomNavigationStyle
BottomSheetBehavior Widget.Design.BottomSheet.Modal Widget.MaterialComponents.BottomSheet.* bottomSheetStyle
BottomSheetDialog BottomSheetDialogFragment Theme.Design.Light.BottomSheetDialog Theme.MaterialComponents.*.BottomSheetDialog ThemeOverlay.MaterialComponents.*.BottomSheetDialog bottomSheetDialogTheme
CollapsingToolbarLayout Widget.Design.CollapsingToolbar N/A N/A
FloatingActionButton Widget.Design.FloatingActionButton Widget.MaterialComponents.FloatingActionButton floatingActionButtonStyle
NavigationView Widget.Design.NavigationView Widget.MaterialComponents.NavigationView navigationViewStyle
Snackbar Widget.Design.Snackbar Widget.MaterialComponents.Snackbar snackbarStyle
TabLayout TabItem Widget.Design.TabLayout Widget.MaterialComponents.TabLayout tabStyle
TextInputLayout TextInputEditText Widget.Design.TextInputLayout Widget.MaterialComponents.TextInputLayout.* textInputStyle
AppCompat widget AppCompat default style AppCompat default style attr MDC-Android widget MDC-Android default style MDC-Android default style attr
AlertDialog.Builder AlertDialog.AppCompat ThemeOverlay.AppCompat.Dialog.Alert alertDialogStyle alertDialogTheme MaterialAlertDialogBuilder MaterialAlertDialog.MaterialComponents ThemeOverlay.MaterialComponents.MaterialAlertDialog alertDialogStyle materialAlertDialogTheme
AppCompatAutoCompleteTextView Widget.AppCompat.AutoCompleteTextView autoCompleteTextViewStyle MaterialAutoCompleteTextView Widget.MaterialComponents.AutoCompleteTextView.* ThemeOverlay.MaterialComponents.AutoCompleteTextView.* autoCompleteTextViewStyle
AppCompatButton Widget.AppCompat.Button buttonStyle MaterialButton Widget.MaterialComponents.Button materialButtonStyle
AppCompatCheckBox Widget.AppCompat.CompoundButton.CheckBox checkboxStyle MaterialCheckbox Widget.MaterialComponents.CompoundButton.CheckBox checkboxStyle
AppCompatImageView N/A N/A ShapeableImageView Widget.MaterialComponents.ShapeableImageView N/A
AppCompatRadioButton Widget.AppCompat.CompoundButton.RadioButton radioButtonStyle MaterialRadioButton Widget.MaterialComponents.CompoundButton.RadioButton radioButtonStyle
AppCompatTextView Widget.AppCompat.TextView N/A MaterialTextView Widget.MaterialComponents.TextView N/A
CardView CardView cardViewStyle MaterialCardView Widget.MaterialComponents.CardView materialCardViewStyle
PopupMenu Widget.AppCompat.PopupMenu.* popupMenuStyle N/A Widget.MaterialComponents.PopupMenu.* popupMenuStyle
SwitchCompat Widget.AppCompat.CompoundButton.Switch switchStyle SwitchMaterial Widget.MaterialComponents.CompoundButton.Switch switchStyle
Toolbar Widget.AppCompat.Toolbar toolbarStyle MaterialToolbar Widget.MaterialComponents.Toolbar toolbarStyle

最新的元件完整列表以及使用文件:https://material.io/develop/android/

示例更新

用 MDC 版本的元件來替換

<!-- Copyright 2020 Google LLC.
   SPDX-License-Identifier: Apache-2.0 -->
-<androidx.cardview.widget.CardView
+<com.google.android.material.card.MaterialCardView
    android:id="@+id/card"
    ...>
    ...
-</androidx.cardview.widget.CardView>
+</com.google.android.material.card.MaterialCardView>

-<androidx.appcompat.widget.SwitchCompat
+<com.google.android.material.switch.SwitchMaterial
    android:id="@+id/switch"
    ... />

顏色

MDC的顏色調色盤直接從 Material Design color system 中繪製。

由於MDC-Android,AppCompat和框架之間共享歷史記錄,因此,顏色屬性集包括以下內容:

  • 框架中已適當命名的現有屬性(例如android:colorBackground
  • AppCompat中已適當命名的現有屬性(例如colorPrimarycolorError
  • 新的屬性由MDC介紹(如colorSurfacecolorOnPrimary等)

再不遷移到Material Design Components 就out啦

MDC視窗小部件使用這些屬性來為其背景,文字,圖示等著色。要了解哪些小部件使用哪種顏色,需要檢查原始碼中的預設小部件樣式。

AppCompat和框架中還存在一些顏色,但不再適用於此新系統。該Theme.MaterialComponents.*主題盡最大努力向後相容他們,例如小部件,這些舊屬性。

<item name="colorAccent">?attr/colorSecondary</item>

但是,您應該考慮不推薦使用這些屬性。使用更合適的MDC屬性或逐步淘汰它們。

請參閱下面的顏色屬性對映表:

注意 AppCompat 中的顏色屬性就不要再使用了

AppCompat /框架顏色屬性 MDC-Android顏色屬性
colorPrimary colorPrimary
colorPrimaryDark colorPrimaryVariantandroid:statusBarColor明確指定)
不適用 colorOnPrimary
colorAccent colorSecondary
不適用 colorSecondaryVariant
不適用 colorOnSecondary
不適用 colorSurface
不適用 colorOnSurface
android:colorBackground android:colorBackground
不適用 colorOnBackground
colorError colorError
不適用 colorOnError
android:textColorPrimaryandroid:textColorSecondary等等。 N / A (建議將MDC設定為“ on”屬性或使用預設值)
colorControlNormalcolorControlHighlightcolorControlActivated N / A (“接通”或ATTRS使用預設偏好MDC) 注意:這些仍然被用來著色MaterialCheckBoxMaterialRadioButtonSwitchMaterialMaterialToolbar圖示

例子

<style name="Theme.App" parent="Theme.MaterialComponents.*">
    ...
    <item name="colorPrimary">@color/navy_700</item>
-    <item name="colorPrimaryDark">@color/navy_900</item>
+    <item name="colorPrimaryVariant">@color/navy_900</item>
-    <item name="colorAccent">@color/green_300</item>
+    <item name="colorSecondary">@color/green_300</item>
+    <item name=”colorSecondaryVariant”>@color/green_500</item>
+    <item name="android:statusBarColor">@color/navy_900</item>
</style>

@color對於包含的按鈕文字顏色,我們還應該使用新的“ on”顏色屬性

<!-- Copyright 2020 Google LLC.
   SPDX-License-Identifier: Apache-2.0 -->
<Button
-    android:textColor="@android:color/white"
+    android:textColor="?attr/colorOnPrimary"
    ... />

字型板式

新的 TextAppearance 樣式/屬性

MDC字型板式直接從Material Design型別系統中提取。表達的意思就是緊貼 Material Design 風格

引入了一組新的TextAppearance.MaterialComponents.*樣式和相應的textAppearance*主題屬性,它們替代了現有的AppCompat /框架樣式。

再不遷移到Material Design Components 就out啦
再不遷移到Material Design Components 就out啦

MDC小部件使用這些屬性來設定文字樣式。要知道哪些視窗小部件使用哪種型別板式,需要檢查原始碼中的預設視窗小部件樣式。

請參閱下面的完整型別樣式和屬性對映表: 13 種型別

AppCompat文字樣式 MDC-Android文字樣式 MDC-Android文字屬性
TextAppearance.AppCompat.Display4 TextAppearance.MaterialComponents.Headline1 textAppearanceHeadline1
TextAppearance.AppCompat.Display3 TextAppearance.MaterialComponents.Headline2 textAppearanceHeadline2
TextAppearance.AppCompat.Display2 TextAppearance.MaterialComponents.Headline3 textAppearanceHeadline3
TextAppearance.AppCompat.Display1 TextAppearance.MaterialComponents.Headline4 textAppearanceHeadline4
TextAppearance.AppCompat.Headline TextAppearance.MaterialComponents.Headline5 textAppearanceHeadline5
TextAppearance.AppCompat.Title TextAppearance.AppCompat.Large TextAppearance.MaterialComponents.Headline6 textAppearanceHeadline6
TextAppearance.AppCompat.Subhead TextAppearance.AppCompat.Menu TextAppearance.MaterialComponents.Subtitle1 textAppearanceSubtitle1
TextAppearance.AppCompat.Small TextAppearance.MaterialComponents.Subtitle2 textAppearanceSubtitle2
TextAppearance.AppCompat.Body1 TextAppearance.MaterialComponents.Body1 textAppearanceBody1
TextAppearance.AppCompat.Body2 TextAppearance.MaterialComponents.Body2 textAppearanceBody2
TextAppearance.AppCompat.Button TextAppearance.MaterialComponents.Button textAppearanceButton
TextAppearance.AppCompat.Caption TextAppearance.MaterialComponents.Caption textAppearanceCaption
不適用 TextAppearance.MaterialComponents.Overline textAppearanceOverline

例子

<com.google.android.material.card.MaterialCardView
    ...>
    ...
    <TextView
        android:id=”@+id/headerText”
-        android:textAppearance="@style/TextAppearance.AppCompat.Title"
+        android:textAppearance="?attr/textAppearanceHeadline6"
        ... />
    <TextView
        android:id=”@+id/subheadText”
        android:textColor="?android:attr/textColorSecondary"
-        android:textAppearance="@style/TextAppearance.AppCompat.Body2"
+        android:textAppearance="?attr/textAppearanceBody2"
        ... />
    <TextView
        android:id=”@+id/supportingText”
        android:textColor="?android:attr/textColorSecondary"
-        android:textAppearance="@style/TextAppearance.AppCompat.Body2"
+        android:textAppearance="?attr/textAppearanceBody2"
        ... />
</com.google.android.material.card.MaterialCardView>

自定義

我們還可以選擇在應用程式主題中覆蓋型別比例,以使用自定義字型系列,XML或通過Android Studio 下載字型:

<!-- Copyright 2020 Google LLC.
   SPDX-License-Identifier: Apache-2.0 -->
<style name="Theme.App" parent="Theme.MaterialComponents.*">
    ...
+    <item name="textAppearanceHeadline6">@style/TextAppearance.App.Headline6</item>
+    <item name="textAppearanceBody2">@style/TextAppearance.App.Body2</item>
</style>

+<style name="TextAppearance.App.Headline6"
+    parent="TextAppearance.MaterialComponents.Headline6">
+    <item name="fontFamily">@font/roboto_mono_medium</item>
+</style>
+<style name="TextAppearance.App.Body2"
+    parent="TextAppearance.MaterialComponents.Body2">
+    <item name="fontFamily">@font/roboto_mono_regular</item>
+</style>

上面我們只是重寫了 13 種型別中的一種。如果你想要改變字型的話,建議也把剩餘的 12 修改了,以保持APP中字型的一致性。

Shape

ShapeAppearance styles/attributes

Shape( Material Design shape system) 是用來處理 MDC 控制元件的邊角的一種方式,分成了小,中,大

這些合適的樣式屬性來自 ShapeAppearance.* styles。包括:cornerFamily (兩種值:rounded cut) 。用 cornerSize 來表示尺寸

再不遷移到Material Design Components 就out啦
再不遷移到Material Design Components 就out啦

MDC小部件使用這些屬性來設定其背景樣式。要了解哪些視窗小部件適用於哪些形狀類別,需要檢查原始碼中的預設視窗小部件樣式。

控制元件背景

實現此功能的類為 MaterialShapeDrawable. 預設情況下,所有的 MDC 控制元件都將此可繪製物件當做背景,我們也可以考慮將它用作自定義 View 的背景。它可以處理形狀主題、陰影、黑色主題等等。

因此。我們不建議使用 android:background 作為 MDC 控制元件的背景。因為它會覆蓋 MaterialShapeDrawable。大多數的 MDC 控制元件的預設 style 都指定了 <item name="android:background">@null</item>

為了避免這種情況,應該使用 shapeApperance/shapeAppearanceOverlaybackgroundTint 屬性來調整背景形狀和顏色。

以下情況需要單獨注意:

  • MaterialButton1.2.0-alpha06 版本前忽略了 android:background 如果你確實需要用這個屬性,考慮使用 AppCompatButton 在你的佈局中。
  • MaterialShapeDrawable 是不支援 gradients 的。如果確實需要的話,最好用 android:background

例子

在我們的示例中我們可以刪除一些由 shape theming 來處理的屬性。

<com.google.android.material.bottomnavigation.BottomNavigationView
-    android:background="@android:color/white"
    ... />

<com.google.android.material.card.MaterialCardView
-    app:cardCornerRadius="2dp"
    ...>
    ...
</com.google.android.material.card.MaterialCardView>

使用 corner familysize 來自定義 shape

我們可以選擇在應用主題中覆蓋形狀樣式來表達我們自己的品牌。

<style name="Theme.App" parent="Theme.MaterialComponents.*">
    ...
+    <item name="shapeAppearanceSmallComponent">@style/ShapeAppearance.App.SmallComponent</item>
+    <item name="shapeAppearanceMediumComponent">@style/ShapeAppearance.App.MediumComponent</item>
+    <item name="shapeAppearanceLargeComponent">@style/ShapeAppearance.App.LargeComponent</item>
</style>

+<style name="ShapeAppearance.App.SmallComponent"
+   parent="ShapeAppearance.MaterialComponents.SmallComponent">
+    <item name="cornerFamily">rounded</item>
+    <item name="cornerSize">8dp</item>
+</style>
+<style name="ShapeAppearance.App.MediumComponent"
+    parent="ShapeAppearance.MaterialComponents.MediumComponent">
+    <item name="cornerFamily">rounded</item>
+    <item name="cornerSize">12dp</item>
+</style>
+<style name="ShapeAppearance.App.LargeComponent"
+    parent="ShapeAppearance.MaterialComponents.LargeComponent">
+    <item name="cornerFamily">rounded</item>
+    <item name="cornerSize">16dp</item>
+</style>

再不遷移到Material Design Components 就out啦
再不遷移到Material Design Components 就out啦

使用 shape theming 的例子

恢復 Button 的自定義漸變背景

-<Button
+<androidx.appcompat.widget.AppCompatButton
    android:background="@drawable/bg_button_gradient"
+    android:textAppearance="?attr/textAppearanceButton"
    ... />

如果使用的是 MDC 1.2.0-alpha-06 或者更新的版本,可以直接使用 MaterialButtonandroid:background。需要注意的是要清空 backgroundTint,因為在預設的 style 中,backgroundTintcolorPrimary

<!-- Copyright 2020 Google LLC.
   SPDX-License-Identifier: Apache-2.0 -->
<Button
    android:background="@drawable/bg_button_gradient"
+    app:backgroundTint="@null"
    ... />