Tworzenie kompletnej aplikacji za pomocą Relay i Jetpack Compose

1. Zanim zaczniesz

Relay to zestaw narzędzi, który umożliwia zespołom projektowanie komponentów UI w programie Figma i wykorzystywanie ich bezpośrednio w projektach Jetpack Compose. Dzięki temu nie trzeba tworzyć żmudnych specyfikacji projektów ani przeprowadzać cykli testów, co pomaga zespołom szybko tworzyć świetne interfejsy użytkownika na Androida.

Z tego ćwiczenia w Codelab dowiesz się, jak zintegrować pakiety interfejsu Relay z procesem tworzenia aplikacji w Compose. Skupia się on na technikach integracji, a nie na całym procesie. Aby dowiedzieć się więcej o ogólnym procesie obsługi Relay, zapoznaj się z podstawowym samouczkiem Relay.

Wymagania wstępne

  • Podstawowe informacje o Compose. Jeśli jeszcze tego nie zrobiono, wykonaj ćwiczenie Podstawy Jetpack Compose.
  • znajomość składni języka Kotlin;

Czego się nauczysz

  • Jak importować pakiety interfejsu
  • Jak integrować pakiety interfejsu użytkownika z architekturą nawigacji i danych
  • Jak opakować pakiety interfejsu użytkownika za pomocą logiki kontrolera.
  • Jak dopasować style z Fimgi do motywu w Compose.
  • Jak zastąpić pakiety interfejsu użytkownika istniejącymi komponentami w wygenerowanym kodzie.

Co utworzysz

  • Realistyczny projekt aplikacji oparty na pakietach Relay dostarczonych przez projektanta. Aplikacja nosi nazwę Reflect i służy do codziennego śledzenia aktywności, a także promuje uważność i zdrowe nawyki. Zawiera kolekcję liczników różnych typów oraz interfejs do ich dodawania i zarządzania nimi. Aplikacja wygląda tak:

Gotowa aplikacja

Czego potrzebujesz

2. Konfiguracja

Pobierz kod

Aby uzyskać kod do tego ćwiczenia, wykonaj jedną z tych czynności:

$ git clone https://github.com/googlecodelabs/relay-codelabs
  • Przejdź do repozytorium relay-codelabs na GitHub, wybierz odpowiednią gałąź, a następnie kliknij Kod > Pobierz plik ZIP i rozpakuj pobrany plik ZIP.

W obu przypadkach gałąź main zawiera kod startowy, a gałąź end – kod rozwiązania.

Instalowanie wtyczki Relay do Android Studio

Jeśli nie masz jeszcze wtyczki Relay dla Android Studio, wykonaj te czynności:

  1. W Android Studio kliknij Ustawienia > Wtyczki.
  2. W polu tekstowym wpisz Relay for Android Studio.
  3. W rozszerzeniu, które pojawi się w wynikach wyszukiwania, kliknij Zainstaluj.

Ustawienia wtyczki Android Studio

  1. Jeśli zobaczysz okno Informacje o prywatności wtyczek innych firm, kliknij Zaakceptuj.
  2. Kliknij OK > Uruchom ponownie.
  3. Jeśli pojawi się okno Potwierdź wyjście, kliknij Wyjdź.

Łączenie Android Studio z Fimą

Relay pobiera pakiety interfejsu użytkownika za pomocą interfejsu API Figma. Aby z niego korzystać, musisz mieć bezpłatne konto Figma i osobisty token dostępu, dlatego są one wymienione w sekcji Co będzie potrzebne.

Jeśli nie masz jeszcze połączonego Android Studio z Figmą, wykonaj te czynności:

  1. Na koncie Figma kliknij ikonę profilu u góry strony i wybierz Ustawienia.
  2. W sekcji Tokeny dostępu wpisz w polu tekstowym opis tokena, a potem naciśnij Enter (lub return w systemie macOS). Wygenerowano token.
  3. Kliknij Skopiuj ten token.

token dostępu wygenerowany w Fimie.

  1. W Android Studio wybierz Narzędzia > Ustawienia przekazu. Pojawi się okno Ustawienia przekaźnika.
  2. W polu tekstowym Token dostępu Figma wklej token dostępu, a następnie kliknij OK. Środowisko zostało skonfigurowane.

3. Sprawdzanie projektu aplikacji

W przypadku aplikacji Reflect współpracowaliśmy z projektantem, który pomógł nam określić kolory, typografię, układ i zachowanie aplikacji. Te projekty zostały stworzone zgodnie z konwencjami Material Design 3, aby aplikacja mogła bezproblemowo współpracować z elementami i motywami Material.

Sprawdzanie ekranu głównego

Ekran główny zawiera listę śledzenia zdefiniowaną przez użytkownika. Umożliwia też zmianę aktywnego dnia i tworzenie innych liczników.

Ekran główny

W Figrze nasz projektant podzielił ten ekran na kilka komponentów, zdefiniował ich interfejsy API i opakował je za pomocą wtyczki Relay for Figma. Po spakowaniu tych komponentów możesz je zaimportować do projektu w Android Studio.

Element ekranu głównego

Sprawdź ekran dodawania i edytowania.

Na ekranie dodawania/edytowania użytkownicy mogą dodawać i edytować lokalizatory. Formularz wyświetlany jest w nieco inny sposób w zależności od typu śledzenia.

Ekran dodawania/edytowania

Podobnie ten ekran jest podzielony na kilka spakowanych komponentów.

Dodawanie i edytowanie komponentów ekranu

Sprawdzanie tematu

Kolory i typografia w tym projekcie są implementowane jako style w programie Figma na podstawie nazw tokenów Material Design 3. Zapewnia to lepszą współpracę z motywami i komponentami Material Design.

Style w Fimmie

4. Importowanie pakietów interfejsu użytkownika

Zanim zaimportujesz pakiety interfejsu do projektu, musisz przesłać do Figmy źródło projektu.

Aby uzyskać link do źródła w Figmie, wykonaj te czynności:

  1. W Figmie kliknij Importuj plik, a następnie wybierz plik ReflectDesign.fig znajdujący się w folderze projektu CompleteAppCodelab.
  2. Kliknij plik prawym przyciskiem myszy i wybierz Kopiuj link. Będziesz go potrzebować w kolejnej sekcji.

88afd168463bf7e5.png

Importowanie pakietów interfejsu do projektu

  1. W Android Studio otwórz projekt ./CompleteAppCodelab.
  2. Kliknij Plik > Nowy > Importuj pakiety interfejsu użytkownika. Pojawi się okno Importowanie pakietów interfejsu użytkownika.
  3. W polu tekstowym Adres URL źródłowy Figmy wklej adres URL skopiowany w poprzedniej sekcji.

f75d0c3e17b6f75.png

  1. W polu tekstowym Motyw aplikacji wpisz com.google.relay.example.reflect.ui.theme.ReflectTheme. Dzięki temu wygenerowane podglądy będą używać motywu niestandardowego.
  2. Kliknij Dalej. Zobaczysz podgląd pakietów interfejsu pliku.
  3. Kliknij Utwórz. Pakiety zostaną zaimportowane do projektu.
  4. Otwórz kartę Projekt i kliknij strzałkę 2158ffa7379d2b2e.png obok folderu ui-packages.

Folder ui-packages

  1. Kliknij 2158ffa7379d2b2e.pngstrzałkę rozszerzania obok jednego z folderów pakietu, aby zobaczyć, że zawiera on plik źródłowy JSON i zależności zasobów.
  2. Otwórz plik źródłowy JSON. Moduł Relay wyświetla podgląd pakietu i jego interfejsu API.

a6105146c4cfb47.png

Tworzenie i generowanie kodu

  1. U góry Android Studio kliknij b3bc77f3c78cac1b.png Utwórz projekt. Wygenerowany kod każdego pakietu jest dodawany do folderu java/com.google.relay.example.reflect. Wygenerowane elementy zawierają wszystkie informacje o układzie i stylu z projektu w Fimie.
  2. Otwórz plik com/google/relay/example/reflect/range/Range.kt.
  3. Pamiętaj, że podglądy w sekcji „Stwórz” są tworzone dla każdej odmiany komponentu. W razie potrzeby kliknij Podziel, aby obok siebie wyświetlić panele kodu i podglądu.

c0d21ab0622ad550.png

5. Integracja komponentów

W tej sekcji przyjrzysz się bliżej wygenerowanemu kodom modułu śledzenia Switch.

Projekt licznika Switch

  1. W Android Studio otwórz plik com/google/relay/example/reflect/switch/Switch.kt.

Switch.kt (wygenerowany)

/**
 * 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()
                }
            }
        }
    }
}
  1. Pamiętaj:
  • Generowany jest cały układstyl z projektu w Fimie.
  • Podelementy są podzielone na osobne elementy składane.
  • Złożone podglądy są generowane dla wszystkich wariantów projektu.
  • Kolory i krój czcionki są zakodowane na stałe. Naprawi to później.

Wkładanie lokalizatora

  1. W Android Studio otwórz plik java/com/google/relay/example/reflect/ui/components/TrackerControl.kt. Ten plik udostępnia dane i logikę interakcji z wykorzystaniem śledzenia nawyków.
  2. Skompiluj i uruchom aplikację w emulatorze. Obecnie ten komponent zwraca dane nieprzetworzone z modelu śledzenia.

5d56f8a7065066b7.png

  1. Zaimportuj do pliku pakiet com.google.relay.example.reflect.switch.Switch.
  2. Zastąp blok Text(text = trackerData.tracker.toString()) blokiem when, który obraca się wokół pola trackerData.tracker.type.
  3. W treści bloku when wywołaj funkcję Switch() Composable, gdy typ to TrackerType.BOOLEAN.

Twój kod powinien wyglądać tak:

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())
}
  1. Utwórz ponownie projekt. Strona główna prawidłowo wyświetla licznik Switch zgodnie z projektem i z danymi na żywo.

4241e78b9f82075b.png

6. Dodawanie stanu i interakcji

Pakiety interfejsu użytkownika są stanowe. Wyświetlany jest prosty wynik przekazanych parametrów. Prawdziwe aplikacje wymagają interakcji i stanu. Obsługa interakcji może być przekazywana do wygenerowanych komponentów jak każdy inny parametr, ale gdzie przechowywać stan, którym te obsługa manipuluje? Jak uniknąć przekazywania tego samego modułu do każdej instancji? Jak można zamienić abstrakcyjne kompozycje pakietów w elementy wielokrotnego użytku? W takich przypadkach zalecamy owinięcie wygenerowanych pakietów w niestandardową funkcję Composable.

Owiń pakiety interfejsu w funkcji kontrolera Composable

Owijanie pakietów interfejsu w funkcji kontrolera Composable umożliwia dostosowywanie prezentacji lub logiki biznesowej oraz, w razie potrzeby, zarządzanie stanem lokalnym. Projektanci nadal mogą aktualizować oryginalne UI Package w Figmie bez konieczności aktualizowania kodu opakowania.

Aby utworzyć kontroler dla lokalizatora Switch:

  1. W Android Studio otwórz plik java/com/google/relay/example/reflect/ui/components/SwitchControl.kt.
  2. W funkcji SwitchControl() Composable podaj te parametry:
  • trackerData: obiekt TrackerData
  • modifier: obiekt dekoracyjny
  • onLongClick: wywołanie interakcji umożliwiające długie naciśnięcie wskaźników w celu ich edycji i usunięcia
  1. Wstaw funkcję Switch() i przekaż modyfikator combinedClickable, aby obsłużyć kliknięcie i długie naciśnięcie.
  2. Przekazywanie wartości z obiektu TrackerData do funkcji Switch(), w tym do metody isToggled().

Gotowa funkcja SwitchControl() wygląda tak:

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)
}
  1. W pliku TrackerControl.kt usuń import funkcji Switch, a potem zastąp funkcję Switch() wywołaniem funkcji SwitchControl().
  2. Dodaj przypadki dla stałych enumeratorów TrackerType.RANGETrackerType.COUNT.

Ukończony blok when wygląda tak:

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 },
        )
}
  1. Utwórz ponownie projekt. Teraz możesz wyświetlać lokalizatory i z nimi wchodzić w interakcję. Ekran główny jest gotowy.

b23b94f0034243d3.png

7. Mapowanie dotychczasowych komponentów

Relay umożliwia programistom dostosowywanie wygenerowanego kodu przez zastąpienie pakietów interfejsu użytkownika istniejącymi komponentami. To świetny sposób na wygenerowanie w kodzie gotowych komponentów lub nawet niestandardowych systemów projektowania.

Mapowanie pola tekstowego

Na tym obrazie widać projekt komponentu Tracker Settings w oknie Dodaj/edytuj licznik:

Projektowanie komponentu ustawień przełącznika

Nasz projektant użył w projektie elementu ReflectTextField, który jest już zaimplementowany w kodzie na podstawie pól tekstowych Material Design 3. Figma nie obsługuje domyślnie pól tekstowych, więc domyślny kod wygenerowany przez Relay wygląda tylko jak projekt, a nie jest funkcjonalnym elementem sterującym.

Aby przetestować bieżącą implementację TrackerSettings:

  1. W Android Studio utwórz i uruchom aplikację w emulatorze.
  2. Przytrzymaj wiersz śledzenia i kliknij Edytuj.
  3. Kliknij pole tekstowe Title i zauważ, że nie reaguje na interakcję.

Aby zastąpić rzeczywiste wdrożenie tego elementu, potrzebujesz 2 rzeczy: pakiet interfejsu tekstowego polaplik mapowania. Na szczęście nasz projektant już zapakował komponenty systemu projektowania w Fimie i użył komponentu pola tekstowego w projekcie Tracker Settings. Domyślnie ten pakiet zagnieżdżony jest generowany jako zależność, ale możesz go zastąpić za pomocą mapowania komponentów.

Komponent Figma dla pola tekstowego z nałożonym wtyczką Relay

Tworzenie pliku mapowania

Wtyczka Relay for Android Studio umożliwia szybkie tworzenie plików mapowania komponentów.

Aby utworzyć plik mapowania:

  1. W Android Studio kliknij text_field prawym przyciskiem myszy pakiet interfejsu użytkownika i wybierz Wygeneruj plik mapowania.

Element menu kontekstowego pliku mapowania do generowania

  1. Pojawi się okno pliku mapowania. Wybierz te opcje:
  • W sekcji Docelowy komponent wybierz Użyj dotychczasowego komponentu i wpisz com.google.relay.example.reflect.ui.components.ReflectTextField.
  • W sekcji Wygenerowany plik zaznacz pole Wygeneruj implementację i odznacz pole Wygeneruj podgląd tworzenia wiadomości.

e776585c3b838b10.png

  1. Kliknij Wygeneruj plik mapowania. Spowoduje to wygenerowanie tego pliku mapowania:

text_field.json

{
  "target": "ReflectTextField",
  "package": "com.google.relay.example.reflect.ui.components",
  "generateImplementation": true,
  "generatePreviews": false,
}

Pliki mapowania komponentów wskazują cel i pakiet klasy Compose oraz opcjonalną kolekcję obiektów fieldMapping. Te mapowania pól umożliwiają przekształcanie parametrów pakietu w oczekiwane parametry usługi Compose. W tym przypadku interfejsy API są identyczne, więc musisz tylko określić klasę docelową.

  1. Utwórz ponownie projekt.
  2. W pliku trackersettings/ TrackerSettings.kt odszukaj wygenerowaną funkcję kompozytową TitleFieldStyleFilledStateEnabledTextConfigurationsInputText() i zwróć uwagę, że zawiera ona wygenerowany komponent ReflectTextField.

TrackerSettings.kt (wygenerowany)

@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)
    )
}
  1. Utwórz ponownie projekt. Teraz możesz korzystać z ustawień śledzenia. Ekran edycji jest gotowy.

8. Mapowanie na tematy Compose

Domyślnie Relay generuje wartości dosłowne dla kolorów i typografii. Zapewnia to dokładność tłumaczenia, ale uniemożliwia komponentom korzystanie z systemu motywów w usłudze Compose. Jest to widoczne, gdy wyświetlasz aplikację w trybie ciemnym:

Podgląd ekranu głównego w trybie ciemnym z nieprawidłowymi kolorami

Komponent nawigacji po dniach jest prawie niewidoczny, a kolory są nieprawidłowe. Aby to naprawić, użyj funkcji mapowania stylów w Relay, aby połączyć style Figmy z tokenami motywu Compose w wygenerowanym kodzie. Dzięki temu zwiększa się spójność wizualna między komponentami Relay a Material Design 3, a także umożliwia obsługę trybu ciemnego.

1fac916db14929bb.png

Tworzenie pliku mapowania stylów

  1. W Android Studio przejdź do katalogu src/main/ui-package-resources i utwórz nowy katalog o nazwie style-mappings. W tym katalogu utwórz plik figma_styles.json z tym kodem:

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"
      }
    }
  }
}

Pliki mapowania motywów są ustrukturyzowane za pomocą 2 obiektów najwyższego poziomu: figmacompose. W tych obiektach definicje kolorów i typów są połączone między obiema środowiskami za pomocą tokenów pośrednich. Dzięki temu wiele stylów Figmy może być mapowanych na jeden wpis motywu w Compose. Jest to przydatne, gdy obsługujesz motywy jasne i ciemne.

  1. Sprawdź plik mapowania, zwracając szczególną uwagę na to, jak mapuje właściwości typograficzne z Figmy do wymagań Compose.

Ponownie importowanie pakietów interfejsu użytkownika

Po utworzeniu pliku mapowania musisz ponownie zaimportować wszystkie pakiety interfejsu użytkownika do projektu, ponieważ podczas pierwszego importowania wszystkie wartości stylów z Fimgi zostały odrzucone, ponieważ nie został podany plik mapowania.

Aby ponownie zaimportować pakiety interfejsu użytkownika:

  1. W Android Studio kliknij Plik > Nowy > Zaimportuj pakiety interfejsu użytkownika. Pojawi się okno Importowanie pakietów interfejsu użytkownika.
  2. polu tekstowym Adres URL źródłowego pliku Figma wpisz adres URL źródłowego pliku Figma.
  3. Zaznacz pole wyboru Przetłumacz style Figmy na motyw tworzenia.
  4. Kliknij Importuj konfigurację niestandardową. Kliknij ikonę folderu, a następnie wybierz utworzony plik: src/main/ui-package-resources/style-mappings/figma_styles.json.
  5. Kliknij Dalej. Zobaczysz podgląd pakietów interfejsu pliku.
  6. Kliknij Utwórz. Pakiety zostaną zaimportowane do projektu.

Okno Importowanie pakietów interfejsu

  1. Zbuduj ponownie projekt, a potem otwórz plik switch/Switch.kt, aby wyświetlić wygenerowany kod.

Switch.kt (wygenerowany)

@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)
    )
}
  1. Zwróć uwagę, że parametr backgroundColor jest ustawiony na pole MaterialTheme.colorScheme.surfaceVariant w obiekcie motywu Compose.
  2. Uruchom projekt i włącz tryb ciemny w emulatorze. Motyw jest prawidłowo zastosowany, a błędy wizualne zostały naprawione.

6cf2aa19fabee292.png

9. Gratulacje

Gratulacje! Wiesz już, jak zintegrować Relay z aplikacjami Compose.

Więcej informacji