Zmapuj komponenty na istniejący kod

Programiści mogą dostosowywać proces generowania kodu, dodając mapowanie między pakietem UI a istniejącym komponentem kodu zamiast wygenerowanego kodu. Jest to przydatne, gdy w obecnej implementacji występują funkcje, których nie można osiągnąć za pomocą wygenerowanego kodu, takie jak animacja lub złożone zachowanie (np. menu).

Deweloperzy określają, jak mapować komponenty za pomocą pliku mapowania. Plik mapowania informuje generator kodu przynajmniej o tym, jak dotrzeć do docelowej funkcji kompozycyjnej, aby umożliwić utworzenie odpowiedniego kodu klienta.

Diagram prezentujący zmapowany komponent

Oto przykład:

W Figmie projektant tworzy komponent Karta, który zawiera wystąpienie komponentu Pasek Play, pakuje oba komponenty i wysyła je do dewelopera.

Gdy deweloper zaimportuje pakiety UI z Figma, w ui-packages zostaną utworzone 2 katalogi: card i play_bar. Podczas tworzenia projektu tworzone są 2 funkcje kompozycyjne: Card i PlayBar. Zazwyczaj Card zawiera w Figmie wystąpienie paska odtwarzania, dlatego w kodzie funkcja kompozycyjna Card zawiera wywołanie funkcji kompozycyjnej PlayBar.

Projektant i programista chcą jednak, aby usługa Card używała istniejącego już elementu kompozycyjnego MyExistingPlaybar, który ma funkcje trudne do opisania w Figmie. Dodaje więc plik mapowania o nazwie play_bar.json, który mapuje pakiet interfejsu play_bar na MyExistingPlaybar:

{
    "target": "MyExistingPlaybar",
    "package": "com.example.myApp"
}

Teraz, gdy deweloper tworzy projekt, Card wywołuje metodę MyExistingPlaybar zamiast PlayBar. Pamiętaj, że MyExistingPlaybar musi mieć te same parametry co PlayBar (chociaż mogą występować pewne różnice, co opisaliśmy w dyrektywach dodatkowych poniżej).

Plik mapowania

W projektach Android Studio pliki mapowania są dodawane do folderu ui-package-resources/mappings obok folderu ui-packages. Podczas kompilacji usługa przekaźnika szuka plików mapowania.

Plik mapowania w widoku projektu

Generowanie pliku mapowania

Usługa przekaźnika może wygenerować plik mapowania dla dowolnego zaimportowanego pakietu UI. Wykonaj te czynności:

  1. Kliknij prawym przyciskiem myszy folder pakietu lub dowolny plik w docelowym folderze ui-package. Wybierz Wygeneruj plik mapowania.

    Wygeneruj afordancję pliku mapowania

  2. Skonfiguruj te opcje w oknie:

    Okno generowania plików mapowania

    • Lokalizacja pliku: określa lokalizację wygenerowanego pliku mapowania.

    • Element docelowy kompozycyjny: ustawia niestandardowy element kompozycyjny, który będzie używany zamiast wygenerowanego elementu kompozycyjnego. Możesz użyć istniejącego funkcji kompozycyjnej lub utworzyć nowy w oknie. Utworzenie nowego elementu kompozycyjnego powoduje utworzenie funkcji kompozycyjnej z tymi samymi parametrami, które są określone w pakiecie interfejsu użytkownika.

    • Wygenerowany plik: ustawia opcje generateImplementation i generatePreview w pliku mapowania. Więcej informacji znajdziesz poniżej w sekcji Mapowanie zawartości pliku.
  3. Kliknij Wygeneruj plik mapowania. W folderze ui-package-resources/mapping zostanie utworzony nowy plik mapowania o określonych konfiguracjach.

Możesz też otworzyć okno Wygeneruj plik mapowania w interfejsie modułu pakietu przekaźnika, wykonując te czynności:

  1. Kliknij dowolny plik pakietu UI wewnątrz docelowego folderu ui-package.

  2. Jeśli okno narzędzia Relay nie otworzy się automatycznie, kliknij ikonę przekazywania, aby je otworzyć.

  3. Kliknij przycisk Wygeneruj plik mapowania w sekcji Opcje pakietu.

    Wygeneruj afordancję pliku mapowania

Nazwa pliku mapowania

Nazwa danego pliku mapowania musi być taka sama jak nazwa folderu pakietu UI w komponencie, który zastępuje. Oznacza to, że play_bar.json mapuje pakiet UI w folderze ui-packages/mappings na istniejący komponent kodu.

Mapowanie zawartości pliku

Plik mapowania zawiera te właściwości:

  • target: (wymagany) nazwa niestandardowej funkcji kompozycyjnej. Domyślnie jest to nazwa funkcji utworzonej przez wygenerowany kod.

    "target" : "CustomComposableName"
    
  • package: (wymagana) nazwa pakietu, w którym znajduje się Twój niestandardowy element kompozycyjny. Domyślnie jest to pakiet funkcji utworzony przez wygenerowany kod.

    "package" : "com.example.podcastapp.ui.components"
    
  • generateImplementation: (opcjonalnie) prawda lub fałsz. Jeśli ma wartość true (prawda), implementacja tego pakietu UI jest nadal tworzona w wygenerowanym pliku kodu. W przypadku wartości false (fałsz) implementacja nie zostanie utworzona. Domyślnie ma wartość Prawda.

    "generateImplementation" : true
    
  • generatePreviews: (opcjonalnie) wybierz true lub false. Jeśli ma wartość prawda, podgląd mapowanego komponentu niestandardowego jest tworzony w wygenerowanym pliku kodu. Jeśli to fałsz, podgląd nie zostanie utworzony. Domyślnie ma wartość Prawda.

    "generatePreviews" : true
    

Zmapowane warianty

Jeśli komponent Figma ma warianty, wygenerowany element kompozycyjny zawiera parametry wyliczeniowe, które kodują wariant (zgodnie z opisem w samouczku Obsługa wariantów projektowych). Jeśli chcesz zmapować komponent Figma z wariantami na istniejący kod, musisz go zmapować na funkcję kompozycyjną, która przyjmuje te same parametry co wygenerowany element kompozycyjny. Na przykład w przypadku komponentu Figma o nazwie Chip z wariantem, którego właściwość to ChipType, wygenerowany przez Chip podpis kompozycyjny wygląda tak:

@Composable
fun Chip(
    modifier: Modifier = Modifier,
    chipType: ChipType = ChipType.Red,
    chipText: String
) { ... }

Jeśli chcesz zmapować komponent Chip Figma na istniejący element kompozycyjny MyChip, podpis dla MyChip musi mieć ten sam podpis co wygenerowany element kompozycyjny (przy założeniu, że nie określono żadnych dodatkowych dyrektyw). Oznacza to, że istniejący komponent kodu może stosować te same wersje projektu co komponent Figma.

Dodatkowe dyrektywy

Jeśli na przykład funkcja kompozycyjna, na którą chcesz kierować reklamy, ma taki podpis:

@Composable
fun MyChip(
    modifier: Modifier = Modifier,
    chipType: ChipType = ChipType.Red,
    description: String  // instead of chipText
) { ... }

Do pliku mapowania możesz dodać blok fieldMappings, który wpłynie na sposób mapowania parametrów. W tym przypadku zawiera mapowanie z parametru chipText w Chip na parametr description w MyChip.

{
    "target": "MyChip",
    "package": "com.example.myApp",
    "fieldMappings": [
        {
            "type": "parameter",
            "source": "chipText",
            "target": "description"
        }
    ]
}

Typy bloku fieldMappings:

  • parameter: mapuje pole pakietu UI na parametr kodu.
    • source: nazwa parametru określona w pakiecie interfejsu użytkownika.
    • target: nazwa parametru określona w komponencie kodu docelowego.
  • lambda: mapuje pole pakietu UI na lambda treści.
    • source: nazwa parametru określona w pakiecie interfejsu użytkownika.
    • target: nazwa parametru określona w komponencie kodu docelowego.
  • modifier: mapuje pole pakietu UI na metodę modifier (modyfikator).

    • source: nazwa parametru określona w pakiecie interfejsu użytkownika.
    • method: metoda w obiekcie modyfikatora, która powinna zostać wywołana w wygenerowanym kodzie.
    • parameter: nazwa parametru w ramach określonej metody modyfikatora.
    • library: kwalifikowana nazwa pakietu do zaimportowania w celu uzyskania dostępu do metody modyfikatora.
    • scope: jedna z dwóch wartości wskazujących zakres modyfikatora:
    • any: modyfikator może być używany w dowolnym zakresie odbiornika.
    • relay: modyfikator musi być używany w zakresie odbiorcy obiektu RelayContainer przekaźnika.