1. 事前準備
Relay 是一種工具包,可讓團隊在 Figma 中設計 UI 元件,並直接在 Jetpack Compose 專案中使用這些元件。無須顧及繁瑣設計規格和品質管理週期,有助團隊快速提供優質的 Android UI。
在本程式碼研究室中,您將瞭解如何將 Relay UI 套件整合至 Compose 開發程序。這份文件著重於整合技巧,而非端對端工作流程。如要瞭解 Relay 的一般工作流程,請參閱 Relay 基本教學課程。
必要條件
- 有 Compose 的基本經驗。如果您尚未完成「Jetpack Compose 基本概念」程式碼研究室,請先完成該研究室。
- 具備 Kotlin 語法經驗。
課程內容
- 如何匯入 UI 套件。
- 如何將 UI 套件與導覽和資料架構整合。
- 如何使用控制器邏輯包裝 UI 套件。
- 如何將 Figma 樣式對應至 Compose 主題。
- 如何在產生的程式碼中,將 UI 套件替換為現有的可組合項。
建構項目
- 根據設計人員提供的 Relay 套件,設計真實的應用程式。這款應用程式名為 Reflect,是一款每日追蹤應用程式,可鼓勵使用者培養正念和良好習慣。其中包含各種類型的追蹤器集合,以及用於新增及管理追蹤器的 UI。應用程式如下圖所示:
軟硬體需求
- Android Studio:Electric Eel 以上版本
- 免費的 Figma 帳戶和個人存取權杖
2. 做好準備
取得程式碼
如要取得本程式碼研究室的程式碼,請執行下列任一操作:
- 從 GitHub 複製
relay-codelabs
存放區:
$ git clone https://github.com/googlecodelabs/relay-codelabs
- 前往 GitHub 上的
relay-codelabs
存放區,選取所需分支,然後依序按一下「Code」>「Download zip」,並解壓縮下載的 ZIP 檔案。
無論是哪種情況,main
分支版本都會包含範例程式碼,end
分支版本則包含解決方案程式碼。
安裝 Relay for Android Studio 外掛程式
如果您還沒有 Relay for Android Studio 外掛程式,請按照下列步驟操作:
- 在 Android Studio 中,依序按一下「Settings」>「Plugins」。
- 在文字方塊中輸入
Relay for Android Studio
。 - 在搜尋結果中顯示的擴充功能上,按一下「安裝」。
- 如果畫面顯示「第三方外掛程式隱私權注意事項」對話方塊,請點選「接受」。
- 依序按一下「確定」>「重新啟動」。
- 如果畫面顯示「確認離開」對話方塊,請按一下「退出」。
將 Android Studio 連結至 Figma
Relay 會使用 Figma API 擷取 UI 套件。如要使用這項功能,您需要免費的 Figma 帳戶和個人存取權杖,因此這兩項項目會列在「所需工具」部分。
如果您尚未將 Android Studio 連結至 Figma,請按照下列步驟操作:
- 在 Figma 帳戶中,按一下頁面頂端的個人資料圖示,然後選取「Settings」。
- 在「Personal access token」部分,在文字方塊中輸入權杖的說明,然後按下
Enter
鍵 (macOS 為return
鍵)。系統會產生權杖。 - 按一下「Copy this token」。
- 在 Android Studio 中,依序選取「Tools」>「Relay Settings」。系統隨即會顯示「Relay settings」對話方塊。
- 在「Figma Access Token」文字方塊中貼上存取權杖,然後按一下「確定」。環境已設定完畢。
3. 查看應用程式的設計
我們與設計人員合作設計了 Reflect 應用程式,包括選擇應用程式的顏色、字體排版、版面配置和行為。我們按照 Material Design 3 慣例建立這些設計,讓應用程式能與 Material 元件和主題完美搭配運作。
查看主畫面
主畫面會顯示使用者定義的追蹤器清單。並提供變更活動日和建立其他追蹤器的操作元素。
在 Figma 中,設計師將這個畫面分割成多個元件,定義其 API,並使用 Relay for Figma 外掛程式封裝這些元件。這些元件套件完成後,您就可以將其匯入 Android Studio 專案。
查看新增/編輯畫面
使用者可以透過新增/編輯畫面新增或編輯追蹤器。顯示的資料表單會因追蹤器類型而略有不同。
同樣地,這個畫面會分成多個已封裝的元件。
查看主題
這項設計的顏色和字體排版是以 Material Design 3 符記名稱做為 Figma 樣式實作。這可提供更佳的 Compose 主題和 Material 元件互通性。
4. 匯入 UI 套件
取得 Figma 來源的連結
您必須先將設計來源上傳至 Figma,才能將 UI 套件匯入專案。
如要取得 Figma 來源的連結,請按照下列步驟操作:
- 在 Figma 中,按一下「Import file」,然後選取
CompleteAppCodelab
專案資料夾中的ReflectDesign.fig
檔案。 - 在檔案上按一下滑鼠右鍵,然後選取「複製連結」。在下一節中會用到這項資訊。
將 UI 套件匯入專案
- 在 Android Studio 中開啟
./CompleteAppCodelab
專案。 - 依序點選「File」>「New」>「Import UI Packages」。畫面上會顯示「Import UI Packages」對話方塊。
- 在「Figma 來源網址」文字方塊中,貼上您在上一個部分複製的網址。
- 在「應用程式主題」文字方塊中輸入
com.google.relay.example.reflect.ui.theme.ReflectTheme
。這樣即可確保系統產生的預覽畫面會使用自訂主題。 - 按一下「繼續」,您會看到檔案的 UI 套件預覽畫面。
- 按一下「建立」,套件會匯入專案。
- 前往「Project」分頁,然後按一下
ui-packages
資料夾旁邊的展開箭頭。
- 按一下其中一個套件資料夾旁的
展開箭頭,然後注意該資料夾包含
JSON
來源檔案和資產依附元件。 - 開啟
JSON
來源檔案。Relay 模組會顯示套件及其 API 的預覽畫面。
建構並產生程式碼
- 在 Android Studio 頂端,按一下
「Make project」。每個套件的產生程式碼都會新增至
java/com.google.relay.example.reflect
資料夾。產生的可組合項包含 Figma 設計中的所有版面配置和樣式資訊。 - 開啟
com/google/relay/example/reflect/range/Range.kt
檔案。 - 請注意,系統會為每個元件變化版本建立 Compose 預覽畫面。視需要按一下「Split」,即可並排查看程式碼和預覽窗格。
5. 整合元件
在本節中,您將進一步查看 Switch 追蹤器的產生程式碼。
- 在 Android Studio 中開啟
com/google/relay/example/reflect/switch/Switch.kt
檔案。
Switch.kt (已產生)
/**
* This composable was generated from the UI Package 'switch'.
* Generated code; don't edit directly.
*/
@Composable
fun Switch(
modifier: Modifier = Modifier,
isChecked: Boolean = false,
emoji: String = "",
title: String = ""
) {
TopLevel(modifier = modifier) {
if (isChecked) {
ActiveOverlay(modifier = Modifier.rowWeight(1.0f).columnWeight(1.0f)) {}
}
TopLevelSynth(modifier = Modifier.rowWeight(1.0f)) {
Label(modifier = Modifier.rowWeight(1.0f)) {
Emoji(emoji = emoji)
Title(
title = title,
modifier = Modifier.rowWeight(1.0f)
)
}
Checkmark {
if (isChecked) {
Icon()
}
}
}
}
}
- 請注意以下事項:
- 系統會產生 Figma 設計中的所有版面配置和樣式。
- 子元素會分割為個別的可組合項。
- 系統會為所有設計變化版本產生可組合項預覽畫面。
- 顏色和字體排版樣式為硬式編碼。您稍後會修正這個問題。
放入智慧手環
- 在 Android Studio 中開啟
java/com/google/relay/example/reflect/ui/components/TrackerControl.kt
檔案。這個檔案會為習慣追蹤器提供資料和互動邏輯。 - 在模擬器中建構並執行應用程式。目前,這個元件會輸出追蹤器模型的原始資料。
- 將
com.google.relay.example.reflect.switch.Switch
套件匯入檔案。 - 將
Text(text = trackerData.tracker.toString())
替換成以trackerData.tracker.type
欄位為樞紐的when
區塊。 - 在
when
區塊的主體中,當類型為TrackerType.BOOLEAN
時,請呼叫Switch()
Composable
函式。
您的程式碼應如下所示:
TrackerControl.kt
// TODO: replace with Relay tracker components
when (trackerData.tracker.type) {
TrackerType.BOOLEAN ->
Switch(
title = trackerData.tracker.name,
emoji = trackerData.tracker.emoji
)
else ->
Text(trackerData.tracker.toString())
}
- 重建專案。主畫面現在會正確顯示 Switch 追蹤器,並以即時資料呈現設計。
6. 新增狀態和互動
UI 套件是無狀態的。所顯示的是傳入參數的簡單結果。但實際的應用程式需要互動和狀態。互動處理常式可像其他參數一樣傳遞至產生的可組合項,但您要將這些處理常式所處理的狀態儲存在何處?如何避免將相同的處理常式傳遞至每個例項?如何將套件的組合抽象化為可重複使用的可組合項?在這種情況下,建議您將產生的套件包裝在自訂 Composable
函式中。
在控制器 Composable
函式中包裝 UI 套件
將 UI 套件包裝在控制器 Composable
函式中,即可自訂呈現或商業邏輯,並視需要管理本機狀態。設計人員仍可自由更新 Figma 中的原始 UI 套件,無須更新包裝函式程式碼。
如要為 Switch 追蹤器建立控制器,請按照下列步驟操作:
- 在 Android Studio 中開啟
java/com/google/relay/example/reflect/ui/components/SwitchControl.kt
檔案。 - 在
SwitchControl()
Composable
函式中傳入下列參數:
trackerData
:TrackerData
物件modifier
:裝飾物件onLongClick
:互動回呼,可讓您長按追蹤器進行編輯和刪除
- 插入
Switch()
函式,並傳入combinedClickable
修飾符,以便處理點按和長按事件。 - 將
TrackerData
物件的值傳遞至Switch()
函式,包括isToggled()
方法。
完成的 SwitchControl()
函式如下列程式碼片段所示:
SwitchControl.kt
package com.google.relay.example.reflect.ui.components
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.google.relay.example.reflect.model.Tracker
import com.google.relay.example.reflect.model.TrackerData
import com.google.relay.example.reflect.model.TrackerType
import com.google.relay.example.reflect.switch.Switch
/*
* A component for controlling switch-type trackers.
*
* SwitchControl is responsible for providing interaction and state management to the stateless
* composable [Switch] generated by Relay. [onLongClick] provides a way for callers to supplement
* the control's intrinsic interactions with, for example, a context menu.
*/
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun SwitchControl(
trackerData: TrackerData,
modifier: Modifier = Modifier,
onLongClick: (() -> Unit)? = null,
) {
Switch(
modifier
.clip(shape = RoundedCornerShape(size = 32.dp))
.combinedClickable(onLongClick = onLongClick) {
trackerData.toggle()
},
emoji = trackerData.tracker.emoji,
title = trackerData.tracker.name,
isChecked = trackerData.isToggled(),
)
}
@Preview
@Composable
fun SwitchControllerPreview() {
val data = TrackerData(
Tracker(
emoji = "🍕",
name = "Ate Pizza",
type = TrackerType.BOOLEAN
)
)
SwitchControl(data)
}
- 在
TrackerControl.kt
檔案中,移除Switch
匯入,然後將Switch()
函式替換為對SwitchControl()
函式的呼叫。 - 新增
TrackerType.RANGE
和TrackerType.COUNT
列舉常數的案例。
完成的 when
區塊如下列程式碼片段所示:
TrackerControl.kt
when (trackerData.tracker.type) {
TrackerType.BOOLEAN ->
SwitchControl(
trackerData = trackerData,
onLongClick = { expanded = true },
)
TrackerType.RANGE ->
RangeControl(
trackerData = trackerData,
onLongClick = { expanded = true },
)
TrackerType.COUNT ->
ValueControl(
trackerData = trackerData,
onLongClick = { expanded = true },
)
}
- 重建專案。您現在可以顯示追蹤器並與其互動。主畫面完成。
7. 對應現有元件
開發人員可以使用 Relay,將 UI 套件替換為現有的可組合項,藉此自訂產生的程式碼。這是在程式碼中輸出即用元件,甚至是自訂設計系統的絕佳方法。
對應文字欄位
下圖為「Add/edit tracker」對話方塊中的 Tracker Settings
元件設計:
我們的設計師在設計中使用了 ReflectTextField
,我們已在 Material Design 3 文字欄位上方建構的程式碼中實作了該元素。Figma 不支援原生文字欄位,因此 Relay 產生的預設程式碼只會顯示設計樣式,並非功能控制項。
如要測試 TrackerSettings
目前的實作方式,請按照下列步驟操作:
- 在 Android Studio 中,在模擬器中建構並執行應用程式。
- 長按追蹤器資料列,然後選取「編輯」。
- 輕觸
Title
文字欄位,並注意它不會回應互動。
如要替換此元素的實際實作項目,您需要兩個項目:文字欄位 UI 套件和對應檔案。幸運的是,我們的設計師已在 Figma 中為設計系統元件進行封裝,並在 Tracker Settings
的設計中使用文字欄位元件。根據預設,這個巢狀套件會以依附元件產生,但您可以使用元件對應功能進行交換。
建立對應檔案
Relay for Android Studio 外掛程式提供建立元件對應檔案的捷徑。
如要建立對應檔案,請按照下列步驟操作:
- 在 Android Studio 中,在
text_field
UI 套件上按一下滑鼠右鍵,然後選取「Generate mapping file」。
- 系統隨即會顯示對應檔案對話方塊。輸入下列選項:
- 在「Target composable」中,選取「Use existing composable」,然後輸入
com.google.relay.example.reflect.ui.components.ReflectTextField
- 在「Generated file」中,勾選「Generate implementation」並取消勾選「Generate Compose Preview」
- 按一下「產生對應檔案」。這會產生下列對應檔案:
text_field.json
{
"target": "ReflectTextField",
"package": "com.google.relay.example.reflect.ui.components",
"generateImplementation": true,
"generatePreviews": false,
}
元件對應檔案會指出 Compose 類別目標和套件,以及選用的 fieldMapping
物件集合。這些欄位對應可讓您將套件參數轉換為預期的 Compose 參數。在這種情況下,API 會相同,因此您只需指定目標類別即可。
- 重建專案。
- 在
trackersettings/
TrackerSettings.kt
檔案中,找出產生的TitleFieldStyleFilledStateEnabledTextConfigurationsInputText()
可組合函式,並注意該函式包含產生的ReflectTextField
元件。
TrackerSettings.kt (產生的)
@Composable
fun TitleFieldStyleFilledStateEnabledTextConfigurationsInputText(
onTitleChanged: (String) -> Unit,
title: String,
modifier: Modifier = Modifier
) {
ReflectTextField(
onChange = onTitleChanged,
labelText = "Title",
leadingIcon = "search",
trailingIcon = "cancel",
supportingText = "Supporting text",
inputText = title,
state = State.Enabled,
textConfigurations = TextConfigurations.InputText,
modifier = modifier.fillMaxWidth(1.0f).requiredHeight(56.0.dp)
)
}
- 重建專案。您現在可以與追蹤器設定欄位互動。編輯畫面已完成。
8. 對應至 Compose 主題
根據預設,Relay 會為顏色和字體排版產生文字值。這可確保翻譯準確度,但會防止元件使用 Compose 主題設定系統。在深色模式下查看應用程式時,這一點就很明顯:
日曆導覽元件幾乎看不見,而且顏色有誤。如要修正這個問題,您可以使用 Relay 中的樣式對應功能,將 Figma 樣式連結至產生程式碼中的 Compose 主題符記。這麼做可提升 Relay 與 Material Design 3 元件之間的視覺一致性,並支援深色模式。
建立樣式對應檔案
- 在 Android Studio 中,前往
src/main/ui-package-resources
目錄,然後建立名為style-mappings
的新目錄。在該目錄中建立包含下列程式碼的figma_styles.json
檔案:
figma_styles.json
{
"figma": {
"colors": {
"Reflect Light/background": "md.sys.color.background",
"Reflect Dark/background": "md.sys.color.background",
"Reflect Light/on-background": "md.sys.color.on-background",
"Reflect Dark/on-background": "md.sys.color.on-background",
"Reflect Light/surface": "md.sys.color.surface",
"Reflect Dark/surface": "md.sys.color.surface",
"Reflect Light/on-surface": "md.sys.color.on-surface",
"Reflect Dark/on-surface": "md.sys.color.on-surface",
"Reflect Light/surface-variant": "md.sys.color.surface-variant",
"Reflect Dark/surface-variant": "md.sys.color.surface-variant",
"Reflect Light/on-surface-variant": "md.sys.color.on-surface-variant",
"Reflect Dark/on-surface-variant": "md.sys.color.on-surface-variant",
"Reflect Light/primary": "md.sys.color.primary",
"Reflect Dark/primary": "md.sys.color.primary",
"Reflect Light/on-primary": "md.sys.color.on-primary",
"Reflect Dark/on-primary": "md.sys.color.on-primary",
"Reflect Light/primary-container": "md.sys.color.primary-container",
"Reflect Dark/primary-container": "md.sys.color.primary-container",
"Reflect Light/on-primary-container": "md.sys.color.on-primary-container",
"Reflect Dark/on-primary-container": "md.sys.color.on-primary-container",
"Reflect Light/secondary-container": "md.sys.color.secondary-container",
"Reflect Dark/secondary-container": "md.sys.color.secondary-container",
"Reflect Light/on-secondary-container": "md.sys.color.on-secondary-container",
"Reflect Dark/on-secondary-container": "md.sys.color.on-secondary-container",
"Reflect Light/outline": "md.sys.color.outline",
"Reflect Dark/outline": "md.sys.color.outline",
"Reflect Light/error": "md.sys.color.error",
"Reflect Dark/error": "md.sys.color.error"
},
"typography": {
"symbols": {
"Reflect/headline/large": "md.sys.typescale.headline-large",
"Reflect/headline/medium": "md.sys.typescale.headline-medium",
"Reflect/headline/small": "md.sys.typescale.headline-small",
"Reflect/title/large": "md.sys.typescale.title-large",
"Reflect/title/medium": "md.sys.typescale.title-medium",
"Reflect/title/small": "md.sys.typescale.title-small",
"Reflect/body/large": "md.sys.typescale.body-large",
"Reflect/body/medium": "md.sys.typescale.body-medium",
"Reflect/body/small": "md.sys.typescale.body-small",
"Reflect/label/large": "md.sys.typescale.label-large",
"Reflect/label/medium": "md.sys.typescale.label-medium",
"Reflect/label/small": "md.sys.typescale.label-small"
},
"subproperties": {
"fontFamily": "font",
"fontWeight": "weight",
"fontSize": "size",
"letterSpacing": "tracking",
"lineHeightPx": "line-height"
}
}
},
"compose": {
"colors": {
"md.sys.color.background": "MaterialTheme.colorScheme.background",
"md.sys.color.error": "MaterialTheme.colorScheme.error",
"md.sys.color.error-container": "MaterialTheme.colorScheme.errorContainer",
"md.sys.color.inverse-on-surface": "MaterialTheme.colorScheme.inverseOnSurface",
"md.sys.color.inverse-surface": "MaterialTheme.colorScheme.inverseSurface",
"md.sys.color.on-background": "MaterialTheme.colorScheme.onBackground",
"md.sys.color.on-error": "MaterialTheme.colorScheme.onError",
"md.sys.color.on-error-container": "MaterialTheme.colorScheme.onErrorContainer",
"md.sys.color.on-primary": "MaterialTheme.colorScheme.onPrimary",
"md.sys.color.on-primary-container": "MaterialTheme.colorScheme.onPrimaryContainer",
"md.sys.color.on-secondary": "MaterialTheme.colorScheme.onSecondary",
"md.sys.color.on-secondary-container": "MaterialTheme.colorScheme.onSecondaryContainer",
"md.sys.color.on-surface": "MaterialTheme.colorScheme.onSurface",
"md.sys.color.on-surface-variant": "MaterialTheme.colorScheme.onSurfaceVariant",
"md.sys.color.on-tertiary": "MaterialTheme.colorScheme.onTertiary",
"md.sys.color.on-tertiary-container": "MaterialTheme.colorScheme.onTertiaryContainer",
"md.sys.color.outline": "MaterialTheme.colorScheme.outline",
"md.sys.color.primary": "MaterialTheme.colorScheme.primary",
"md.sys.color.primary-container": "MaterialTheme.colorScheme.primaryContainer",
"md.sys.color.secondary": "MaterialTheme.colorScheme.secondary",
"md.sys.color.secondary-container": "MaterialTheme.colorScheme.secondaryContainer",
"md.sys.color.surface": "MaterialTheme.colorScheme.surface",
"md.sys.color.surface-variant": "MaterialTheme.colorScheme.surfaceVariant",
"md.sys.color.tertiary": "MaterialTheme.colorScheme.tertiary",
"md.sys.color.tertiary-container": "MaterialTheme.colorScheme.tertiaryContainer"
},
"typography": {
"symbols": {
"md.sys.typescale.display-large": "MaterialTheme.typography.displayLarge",
"md.sys.typescale.display-medium": "MaterialTheme.typography.displayMedium",
"md.sys.typescale.display-small": "MaterialTheme.typography.displaySmall",
"md.sys.typescale.headline-large": "MaterialTheme.typography.headlineLarge",
"md.sys.typescale.headline-medium": "MaterialTheme.typography.headlineMedium",
"md.sys.typescale.headline-small": "MaterialTheme.typography.headlineSmall",
"md.sys.typescale.title-large": "MaterialTheme.typography.titleLarge",
"md.sys.typescale.title-medium": "MaterialTheme.typography.titleMedium",
"md.sys.typescale.title-small": "MaterialTheme.typography.titleSmall",
"md.sys.typescale.body-large": "MaterialTheme.typography.bodyLarge",
"md.sys.typescale.body-medium": "MaterialTheme.typography.bodyMedium",
"md.sys.typescale.body-small": "MaterialTheme.typography.bodySmall",
"md.sys.typescale.label-large": "MaterialTheme.typography.labelLarge",
"md.sys.typescale.label-medium": "MaterialTheme.typography.labelMedium",
"md.sys.typescale.label-small": "MaterialTheme.typography.labelSmall"
},
"subproperties": {
"font": "fontFamily",
"weight": "fontWeight",
"size": "fontSize",
"tracking": "letterSpacing",
"line-height": "lineHeight"
}
},
"options": {
"packages": {
"MaterialTheme": "androidx.compose.material3"
}
}
}
}
主題對應檔案的結構包含兩個頂層物件:figma
和 compose
。在這些物件中,顏色和類型定義會透過中繼符號連結兩個環境。這樣一來,多個 Figma 樣式就能對應至單一 Compose 主題項目,這在您支援淺色和深色主題時相當實用。
- 查看對應檔案,特別是如何將 Figma 的字體排版屬性重新對應至 Compose 預期的屬性。
重新匯入 UI 套件
建立對應檔案後,您必須將所有 UI 套件重新匯入專案,因為在初次匯入時,系統會捨棄所有 Figma 樣式值,因為沒有提供對應檔案。
如要重新匯入 UI 套件,請按照下列步驟操作:
- 在 Android Studio 中,依序點選「File」>「New」>「Import UI Packages」。畫面上會顯示「Import UI Packages」對話方塊。
- 在「Figma 來源網址」文字方塊中,輸入 Figma 來源檔案的網址。
- 選取「將 Figma 樣式轉譯為 Compose 主題」核取方塊。
- 選取「匯入自訂設定」。按一下資料夾圖示,然後選取您剛建立的檔案:
src/main/ui-package-resources/style-mappings/figma_styles.json
。 - 按一下「繼續」,您會看到檔案的 UI 套件預覽畫面。
- 按一下「建立」,套件會匯入專案。
- 重新建構專案,然後開啟
switch/Switch.kt
檔案,查看產生的程式碼。
Switch.kt (產生的)
@Composable
fun ActiveOverlay(
modifier: Modifier = Modifier,
content: @Composable RelayContainerScope.() -> Unit
) {
RelayContainer(
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
isStructured = false,
radius = 32.0,
content = content,
modifier = modifier.fillMaxWidth(1.0f).fillMaxHeight(1.0f)
)
}
- 請注意,如何將
backgroundColor
參數設為 Compose 主題物件中的MaterialTheme.colorScheme.surfaceVariant
欄位。 - 在模擬器中執行專案並開啟深色模式。主題已正確套用,視覺錯誤也已修正。
9. 恭喜
恭喜!您已瞭解如何將 Relay 整合至 Compose 應用程式!