1. 始める前に
Relay は、Figma で UI コンポーネントを設計し、それを Jetpack Compose プロジェクトで直接使用するためのツールキットです。煩雑なデザイン仕様や QA サイクルが不要であるため、優れた Android UI をすばやく提供できるようになります。
この Codelab では、Relay UI パッケージを Compose 開発プロセスに統合する方法を学びます。これは統合手法に重点を置いたものであり、開始から完了までのワークフローを説明するものではありません。Relay の一般的なワークフローについては、Relay の基本チュートリアルをご覧ください。
前提条件
- Compose に関する基本的な経験。基本的な経験がない場合には、Jetpack Compose の基本の Codelab を受講してください。
- Kotlin の構文に関する経験。
学習内容
- UI パッケージをインポートする方法。
- UI パッケージをナビゲーションとデータ アーキテクチャに統合する方法。
- UI パッケージをコントローラのロジックでラップする方法。
- Figma スタイルを Compose テーマにマッピングする方法。
- 生成されたコードで UI パッケージを既存のコンポーザブルに置き換える方法。
作成するアプリの概要
- デザイナーが提供する Relay パッケージに基づき、現実的なアプリデザインを実装します。作成するアプリは Reflect という毎日のマインドフルネスと健康的な習慣をトラッキングするアプリです。これにはさまざまなタイプのトラッカーが含まれており、またトラッカーの追加、管理のための UI が用意されています。アプリは次のようなものです。
必要なもの
- Android Studio の最新バージョン
- 無料の Figma アカウントと個人用アクセス トークン
2. 設定する
コードを取得する
この Codelab のコードを取得するには、以下のいずれかを実行します。
- 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
」と入力します。 - 検索結果に表示される拡張機能で、[Install] をクリックします。
- [Third-party plugins privacy note] ダイアログが表示された場合は、[Accept] をクリックします。
- [OK] > [Restart] をクリックします。
- [Confirm exit] ダイアログが表示されたら、[Exit] をクリックします。
Android Studio と Figma を連携させる
Relay は Figma API を使って UI パッケージを取得します。Figma を使用するには、無料の Figma アカウントと個人用アクセス トークンが必要です。これらは「必要なもの」セクションでも挙げられています。
まだ Android Studio と Figma が連携していない場合は、次の手順に沿って連携させます。
- Figma アカウントで、ページの一番上にあるプロフィール アイコンをクリックし、[Settings] を選択します。
- [Personal access tokens] セクションで、テキスト ボックスにトークンの説明を記入し、
Enter
(macOS の場合はreturn
)を押すと、トークンが生成されます。 - [Copy this token] をクリックします。
- Android Studio で [Tools] > [Relay Settings] をクリックします。[Relay settings] ダイアログが開きます。
- [Figma Access Token] テキスト ボックスにアクセス トークンを貼り付け、[OK] をクリックします。これで環境が設定されました。
3. アプリのデザインを確認する
Reflect アプリでは、デザイナーと協力してアプリのカラー、タイポグラフィ、レイアウト、動作を定義しています。マテリアル デザイン 3 規則に沿ってデザインを行い、アプリがマテリアル コンポーネントやテーマとシームレスに連携するようにしています。
ホーム画面を確認する
ホーム画面にはユーザーが選択したトラッカーのリストが表示されます。アクティブな日付を変更し、他のトラッカーを作成するためのアフォーダンスも用意されています。
デザイナーは Figma でこの画面を複数のコンポーネントに分割し、API を定義して、Relay for Figma プラグインによってパッケージ化しました。コンポーネントをパッケージ化すると、Android Studio プロジェクトにインポートできるようになります。
追加と編集画面を確認する
追加と編集画面で、ユーザーはトラッカーを追加または編集できます。表示されるフォームはトラッカーのタイプによって若干異なります。
同様に、この画面も複数のパッケージ化されたコンポーネントに分割されています。
テーマを確認する
このデザインのカラーとタイポグラフィは、マテリアル デザイン 3 のトークン名に基づき、Figma スタイルとして実装されています。これにより、Compose テーマとマテリアル コンポーネントの高い相互運用性を確保できます。
4. UI パッケージをインポートする
Figma ソースのリンクを取得する
UI パッケージをプロジェクトにインポートする前に、デザインソースを Figma にアップロードする必要があります。
Figma ソースのリンクを取得する手順は次のとおりです。
- Figma で [Import file] をクリックして、Codelab プロジェクト フォルダにある
ReflectDesign.fig
ファイルを選択します。 - ファイルを右クリックして、[Copy link] を選択します。コピーしたリンクは次のセクションで必要になります。
UI パッケージをプロジェクトにインポートする
- Android Studio で
./CompleteAppCodelab
プロジェクトを開きます。 - [File] > [New] > [Import UI Packages] をクリックします。[Import UI Packages] ダイアログが開きます。
- [Figma source URL] テキスト ボックスに、先ほどのセクションでコピーした URL を貼り付けます。
- [App theme] テキスト ボックスに「
com.google.relay.example.reflect.ui.theme.ReflectTheme
」と入力します。これにより、カスタムテーマを使用したプレビューが生成されます。 - [Next] をクリックします。ファイルの UI パッケージのプレビューが表示されます。
- [Create] をクリックします。パッケージがプロジェクトにインポートされます。
- [Project] タブに移動し、
ui-packages
フォルダの横にある展開矢印をクリックします。
- いずれかのパッケージ フォルダの横にある展開矢印
をクリックすると、
JSON
ソースファイルとアセットの依存関係が含まれていることがわかります。 JSON
ソースファイルを開きます。Relay モジュールにパッケージのプレビューと API が表示されます。
コードを構築し生成する
- Android Studio の一番上にある
Make project アイコンをクリックします。各パッケージの生成されたコードが
java/com.google.relay.example.reflect
ファイルに追加されます。生成されたコンポーザブルには、Figma デザインのすべてのレイアウトとスタイル設定情報が含まれています。 - 必要に応じて [Split] をクリックすると、コードとプレビュー ペインを横に並べて表示できます。
range/Range.kt
ファイルを開くと、Compose プレビューがコンポーネントのバリエーションごとに作成されていることがわかります。
5. コンポーネントを統合する
このセクションでは、生成された Switch トラッカーのコードを詳しく確認します。
- Android Studio で
com/google/relay/example/reflect/switch/Switch.kt
ファイルを開きます。
Switch.kt(生成されたコード)
/**
* This composable was generated from the switch UI Package.
* Generated code; don't edit directly.
*/
@Composable
fun Switch(
modifier: Modifier = Modifier,
isChecked: Boolean = false,
isPressed: Boolean = false,
emoji: String = "",
title: String = ""
) {
TopLevel(modifier = modifier) {
if (isChecked) {
ActiveOverlay(modifier = Modifier.rowWeight(1.0f).columnWeight(1.0f)) {}
}
if (isPressed) {
State(modifier = Modifier.rowWeight(1.0f).columnWeight(1.0f)) {}
}
TopLevelSynth {
Label(modifier = Modifier.rowWeight(1.0f)) {
Emoji(emoji = emoji)
Title(
title = title,
modifier = Modifier.rowWeight(1.0f)
)
}
if (isChecked) {
Checkmark {
Vector(modifier = Modifier.rowWeight(1.0f).columnWeight(1.0f))
}
}
}
}
}
- 次の点に注意してください。
- Figma デザインのすべてのレイアウトとスタイルが生成されています。
- サブコンポーネントは個別のコンポーザブルに分割されています。
- コンポーザブル プレビューがすべてのデザイン バリエーションで生成されています。
- カラーとタイポグラフィのスタイルはハードコードされています。これは後で修正できます。
トラッカーを挿入する
- Android Studio で
java/com/google/relay/example/reflect/ui/components/TrackerControl.kt
ファイルを開きます。このファイルは習慣トラッカーにデータと操作ロジックを提供します。現時点では、このコンポーネントはトラッカー モデルからの元データを出力しています。
com.google.relay.example.reflect.switch.Switch
パッケージをファイルにインポートします。trackerData.tracker.type
フィールドにピボットされたwhen
ブロックを作成します。when
ブロックの本文で、タイプがTrackerType.BOOLEAN
のときにSwitch()
Composable
関数を呼び出します。
コードの内容は次のようになります。
TrackerControl.kt
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 パッケージをラップする
コントローラ Composable
関数で UI パッケージをラップすると、表示またはビジネス ロジックをカスタマイズでき、必要な場合にはローカルの状態を管理することもできます。デザイナーは引き続きオリジナルの UI パッケージを Figma でアップデートできます。ラッパーコードをアップデートする必要はありません。
Switch トラッカーのコントローラを作成する手順は以下のとおりです。
- Android Studio で
java/com/google/relay/example/reflect/ui/components/SwitchControl.kt
ファイルを開きます。 SwitchControl()
Composable
関数で、次のパラメータを渡します。
trackerData
:TrackerData
オブジェクトmodifier
: デコレータ オブジェクトonLongClick
: トラッカーの長押しで編集と削除ができるインタラクション コールバック
modifier
combinedClickable
修飾子をSwitch()
関数に渡し、クリックと長押しを処理します。TrackerData
オブジェクトの値をisToggled()
メソッドも含め、Switch()
関数に渡します。
完成した 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
.height(64.dp)
.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
ブロックは次のコード スニペットのようになります。
SwitchControl.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 trackerSTRONG] ダイアログの Switch Tracker Editor
のデザインです。
デザイナーはデザインに ReflectTextField
を使用しました。これはすでにマテリアル デザイン 3 のテキスト フィールドの上に構築されたコードに実装しています。Figma はネイティブにはテキスト フィールドに対応していないため、Relay で生成されたデフォルト コードはデザインのみであり、コントロールとしては機能しません。
この要素の実際の実装に変更するには、テキスト フィールドの UI パッケージとファイルのマッピングの 2 つが必要となります。デザイナーはすでに Figma のデザイン システム コンポーネントをパッケージ化し、Tracker Editor
のデザインにボタン コンポーネントを使用しています。デフォルトでは、このネストされたパッケージは設定バーパッケージの依存関係として生成されますが、切り替えにはコンポーネント マッピングを使用します。
マッピング ファイルを作成する
Relay for Android Studio プラグインには、コンポーネント マッピング ファイルをすばやく作成する機能があります。
マッピング ファイルを作成する手順は次のとおりです。
- Android Studio で
text_field
UI パッケージを右クリックして、[Generate mapping file] を選択します。
- ファイルに次のコードを入力します。
text_field.json
{
"target": "ReflectTextField",
"package": "com.google.relay.example.reflect.ui.components",
"generatePreviews": false
}
Component-mapping ファイルは 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.requiredHeight(56.0.dp)
)
}
8. Compose テーマにマッピングする
デフォルトでは、Relay はカラーとタイポグラフィのリテラル値を生成します。これによって正確に変換されることを徹底できますが、コンポーネントは Compose テーマ設定システムを使用できなくなります。アプリをダークモードで表示すると、問題がよくわかります。
日付のナビゲーション コンポーネントはほとんど読み取れず、カラーが適切ではありません。この問題を解決するには、Relay でスタイル マッピング機能を使って、Figma スタイルを生成されたコードの Compose テーマトークンにリンクします。これにより、Relay とマテリアル デザイン 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"
}
}
}
}
テーマ マッピング ファイルは 2 種類の高レベルのオブジェクト、figma
と compose
で構成されています。これらのオブジェクト内で、カラーとタイプの定義が中間トークン経由で両方の環境間でリンクされます。これにより、複数の Figma スタイルを単一の Compose テーマエントリにマッピングできるため、ライトモードとダークモードに対応する際に役立ちます。
- マッピング ファイルを確認します。特に Figma のタイポグラフィ プロパティがどのように Compose の対象に再マッピングされているかを確認します。
UI パッケージを再インポートする
マッピング ファイル作成後に、すべての UI パッケージをプロジェクトに再インポートする必要があります。マッピング ファイルがなかったため、すべての Figma スタイル値が最初のインポート時に破棄されているからです。
UI パッケージを再インポートする手順は以下のとおりです。
- Android Studio で [File] > [New] > [Import UI Packages] をクリックします。[Import UI Packages] ダイアログが開きます。
- [Figma source URL] テキスト ボックスに、Figma ソースファイルの URL を入力します。
- [Translate Figma styles to Compose theme] チェックボックスをオンにします。
- [Next] をクリックします。ファイルの UI パッケージのプレビューが表示されます。
- [Create] をクリックします。パッケージがプロジェクトにインポートされます。
- プロジェクトを再ビルドして、
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 アプリに統合する方法を学びました。