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

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

您可以使用 Material Theme Builder 工具遷移顏色。

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

詞彙

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

限制

遷移前,請注意下列限制:

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

步驟 1:評估設計系統

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

Step 2:找出主題來源檔案

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

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

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

steps 3:遷移顏色

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

範例:

XML 顏色名稱 Material 3 角色
colorPrimary primary
colorPrimaryDark/colorPrimaryVariant primaryContainer 或 secondary
colorAccent secondary 或 tertiary
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 程式碼中,定義 Shapes 物件,複製 XML 形狀定義。
    2. 將這個 Shapes 物件提供給 MaterialTheme。

      詳情請參閱形狀。

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

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

      詳情請參閱字體排版。

Compose 角色 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 中定義的全新實驗性 Styles API,將樣式做為參數或修飾符傳遞至可組合函式,或使用定義的樣式建立分層、可重複使用的可組合函式變化版本。

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

  • 模式:如果 XML 元素使用自訂樣式 (例如 style="@style/MyPrimaryButton"),請勿嘗試在內嵌中複製樣式。而是建議建立特定的可組合函式。
  • 範例:
    • XML: <Button style="@style/MyPrimaryButton" ... />
    • Compose: MyPrimaryButton(onClick = { ... })
  • 常見屬性群組:如果樣式設定了常見修飾符 (例如 padding + height),請將其擷取至可讀取的擴充功能屬性或共用修飾符變數。

常見例子

XML 撰寫
Theme.Material3.* MaterialTheme(colorScheme, typography, shapes) { }
TextAppearance.Material3.BodyMedium TextStyle(...) 定義於 Typography(bodyMedium = ...)
ShapeAppearance.*.SmallComponent Shapes(small = RoundedCornerShape(X.dp))
Widget.Material3.Button Button(colors = ButtonDefaults.buttonColors(...))
Widget.Material3.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 TextStyle的fontSize = X.sp

步驟 6:驗證主題遷移

請一律使用原始 XML 主題中的現有主題值,做為 Compose 中新 Material Design 主題設定的可靠資料來源。請勿在遷移期間建立新的主題值,以維持品牌一致性,並避免視覺迴歸。

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