在 Compose 中將 XML 主題遷移至 Material 3

在現有應用程式中導入 Compose 時,必須遷移 Material XML 主題,才能在 Compose 元件中使用 MaterialTheme。這表示應用程式的主題設計將有兩個可靠資料來源:以 View 為基礎的主題和 Compose 主題。如要進行樣式變更,您必須在多個位置進行。應用程式完全遷移至 Compose 後,請移除 XML 主題。

您可以使用 Material Design 主題設定建構工具遷移顏色。

從 XML 遷移至 Compose 時,請將主題設定遷移至 Material 3 Compose 主題設定。

詞彙解釋

字詞 定義
MaterialTheme 可組合函式,可為 Compose UI 元件提供主題 (顏色、字體排版、形狀)。
Shape 用於為 MaterialTheme 定義自訂元件形狀的 Compose 物件。
Typography Compose 物件,用於為 MaterialTheme 定義自訂文字樣式 (字型系列、大小、粗細)。
Color 用於定義 MaterialTheme 自訂色彩配置的 Compose 物件。
XML 主題 在 XML 檔案中定義的 Android 主題系統,供 View 系統使用。

限制

遷移前請注意下列限制:

  • 本指南僅著重於遷移至 Material 3。如要從其他設計系統遷移,請參閱「Material 2」或「Compose 中的自訂設計系統」。
  • 最終目標是完全遷移至 Compose,這樣就能移除 XML 主題設定。本指南說明如何遷移,但未說明如何最終移除 XML 主題設定。

步驟 1:評估設計系統

找出 XML 檢視專案中使用的設計系統。 分析遷移路徑和必要步驟,將現有設計系統遷移至 Compose 中的 Material 3。

步驟 2:找出主題來源檔案

在 XML 中,您會寫入 ?attr/colorPrimary。在 Compose 中,您可以使用 MaterialTheme.* 存取主題值:

找出並定位主題設定所需的所有 XML 資源和檔案:淺色和深色色彩配置與限定詞、主題、形狀、尺寸、排版、樣式和其他相關檔案。

字串等資源可直接重複使用,不需遷移。

步驟 3:遷移顏色

關鍵原則:XML 使用具名的十六進位顏色。 Material 3 使用語意角色 (例如 primaryonPrimarysurface)。請停止依十六進位值命名顏色,改用角色命名。

例如:

XML 顏色名稱 Material 3 角色
colorPrimary primary
colorPrimaryDark/colorPrimaryVariant primaryContainersecondary
colorAccent secondarytertiary
colorOnPrimary onPrimary
android:colorBackground background
colorSurface surface
colorOnSurface onSurface
colorError error
colorOnError onError
colorOutline outline
colorSurfaceVariant surfaceVariant
colorOnSurfaceVariant onSurfaceVariant

將 XML 中的深色和淺色色彩配置,遷移至 Material 3 Compose 中的對應項目。

步驟 4:遷移自訂形狀和字體排版

  • 如果您的應用程式使用自訂形狀:

    1. 在 Compose 程式碼中,定義 Shape 物件,複製 XML 形狀定義。
    2. 將這個 Shape 物件提供給 MaterialTheme

      詳情請參閱「形狀」。

  • 如果應用程式使用自訂字體排版:

    1. 在 Compose 程式碼中定義 Typography 物件,複製 XML 文字樣式和字型定義。
    2. 將這個 Typography 物件提供給 MaterialTheme

      詳情請參閱「字體排版」。

撰寫角色 XML 名稱
displayLarge TextAppearance.Material3.DisplayLarge
displayMedium TextAppearance.Material3.DisplayMedium
displaySmall TextAppearance.Material3.DisplaySmall
headlineLarge TextAppearance.Material3.HeadlineLarge
headlineMedium TextAppearance.Material3.HeadlineMedium
headlineSmall TextAppearance.Material3.HeadlineSmall
titleLarge TextAppearance.Material3.TitleLarge
titleMedium TextAppearance.Material3.TitleMedium
titleSmall TextAppearance.Material3.TitleSmall
bodyLarge TextAppearance.Material3.BodyLarge
bodyMedium TextAppearance.Material3.BodyMedium
bodySmall TextAppearance.Material3.BodySmall
labelLarge TextAppearance.Material3.LabelLarge
labelMedium TextAppearance.Material3.LabelMedium
labelSmall TextAppearance.Material3.LabelSmall

步驟 5:遷移樣式 (styles.xml)

XML 樣式 (styles.xml) 系統會定義下列項目的樣式和外觀: 1. 視窗和對話方塊的小工具、元件和主題 2. 字體排版 3. 主題和疊加層 4. 形狀

XML 檢視區塊和元件會合併多個屬性來建立樣式。他們會透過兩種不同方式,從 styles.xml 設定樣式: 1. 在 XML 檢視畫面中直接且明確地設定「style="@style/..."」 2. 為元件間接且隱含地設定樣式,做為較大主題 (theme.xml) 的一部分

Compose 中沒有直接對應的樣式,而是將樣式做為可組合函式的參數傳遞、在 AppTheme 中定義,或是建立具有定義樣式的分層可重複使用可組合函式變體。

請根據樣式和基本元件提供不同的 @Composable 函式,標示這些元件的樣式和用途差異。

  • 模式:如果 XML 元素使用自訂樣式 (例如 style="@style/MyPrimaryButton"),請勿嘗試內嵌複製樣式。請改為建議建立特定可組合函式。
  • 範例:
    • XML: <Button style="@style/MyPrimaryButton" ... />
    • 撰寫:MyPrimaryButton(onClick = { ... })
  • 常見屬性群組:如果樣式設定了常見的修飾符 (例如邊框間距 + 高度),請將這些修飾符擷取至可讀取的擴充功能屬性或共用的 Modifier 變數。

常見範例

XML 撰寫
Theme.MaterialComponents.* MaterialTheme(colorScheme, typography, shapes) { }
TextAppearance.Material3.BodyMedium Typography(bodyMedium = ...) 中定義的 TextStyle(...)
ShapeAppearance.*.SmallComponent Shapes(small = RoundedCornerShape(X.dp))
Widget.MaterialComponents.Button Button(colors = ButtonDefaults.buttonColors(...))
Widget.MaterialComponents.CardView Card(shape=..., elevation=..., colors=...)
Widget.*.TextInputLayout.OutlinedBox OutlinedTextField(colors = OutlinedTextFieldDefaults.colors(...))
Widget.*.Chip.Filter FilterChip(colors = FilterChipDefaults.filterChipColors(...))
Widget.*.Toolbar.Primary TopAppBar(colors = TopAppBarDefaults.topAppBarColors(...))
Widget.*.FloatingActionButton FloatingActionButton(containerColor = ...)
backgroundTint ComponentDefaults.ComponentColors()containerColor
android:textColor ComponentDefaults.ComponentColors()contentColor
cornerRadius shape = RoundedCornerShape(X.dp)
android:elevation elevation = ComponentDefaults.elevation(defaultElevation = X.dp)
android:padding contentPadding = PaddingValues(...)Modifier.padding()
android:minHeight Modifier.heightIn(min = X.dp)
strokeColor + strokeWidth border = BorderStroke(width, color)
android:textSize TextStylefontSize = X.sp

步驟 6:驗證主題遷移作業

一律使用原始 XML 主題的現有主題值,做為 Compose 中新版 Material Design 主題的單一事實來源。遷移期間請勿建立新的主題值,以免品牌不一致,並避免視覺效果回歸。

確認所有新的 Compose 主題值都與現有的 XML 值相符。 請勿對任何遷移的值進行硬式編碼。