Mappare i componenti al codice esistente

Gli sviluppatori possono personalizzare il processo di generazione del codice fornendo una mappatura tra un pacchetto UI e un componente di codice esistente anziché il codice generato. Questo è utile quando l'implementazione esistente include funzionalità che non possono essere raggiunte dal codice generato, come animazioni o comportamenti complessi (ad esempio un menu a discesa).

Gli sviluppatori specificano come mappare i componenti utilizzando un file di mappatura. Un file di mappatura indica al generatore di codice, come minimo, come raggiungere la funzione composable di destinazione in modo da poter creare il codice client corretto.

Diagramma di panoramica dei componenti mappati

Ecco un esempio:

In Figma, un designer crea un componente Scheda che contiene un'istanza di un componente Barra di riproduzione, pacchettizza entrambi i componenti e li invia a un sviluppatore.

Quando lo sviluppatore importa i pacchetti UI da Figma, in ui-packages vengono create due directory: card e play_bar. Quando viene creato il progetto, vengono create due funzioni composable: Card e PlayBar. In genere, poiché Scheda contiene un'istanza di Barra di riproduzione in Figma, nel codice la funzione componibile Card contiene una chiamata al componibile PlayBar.

Tuttavia, il designer e lo sviluppatore vogliono che Card utilizzi un composable esistente, MyExistingPlaybar, con funzionalità difficili da descrivere in Figma. Lo sviluppatore aggiunge quindi un file di mappatura denominato play_bar.json che mappa il pacchetto UI play_bar a MyExistingPlaybar:

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

Ora, quando lo sviluppatore compila il progetto, Card chiama MyExistingPlaybar instead of PlayBar. Tieni presente che MyExistingPlaybar deve avere gli stessi parametri di PlayBar (anche se possono esserci alcune differenze, come descritto nelle Direttive aggiuntive di seguito).

File di mappatura

Nei progetti Android Studio, i file di mappatura vengono aggiunti in ui-package-resources/mappings accanto alla cartella ui-packages. Relay cerca i file di mappatura durante la compilazione.

File di mappatura nella visualizzazione del progetto

Generare un file di mappatura

Relay può generare un file di mappatura per qualsiasi pacchetto UI importato. Segui questi passaggi:

  1. Fai clic con il tasto destro del mouse sulla cartella del pacchetto o su un file all'interno della cartella ui-package di destinazione. Seleziona Genera file di mappatura.

    Genera affordance per il file di mappatura

  2. Configura le seguenti opzioni nella finestra di dialogo:

    Finestra di dialogo per la generazione di file di mappatura

    • Posizione del file:imposta la posizione del file di mappatura generato.

    • Composable target:imposta il composable personalizzato utilizzato al posto del composable generato. Puoi scegliere di utilizzare un composable esistente o crearne uno nuovo dalla finestra di dialogo. La creazione di un nuovo composable genera un composable con gli stessi parametri definiti nel pacchetto UI.

    • File generato: imposta le opzioni generateImplementation e generatePreview nel file di mappatura. Per ulteriori dettagli, consulta la sezione Mappare i contenuti dei file.
  3. Fai clic su Genera file di mappatura. Viene creato un nuovo file di mappatura all'interno della cartella ui-package-resources/mapping con le configurazioni specificate.

Puoi anche aprire la finestra di dialogo Genera file di mappatura dall'interfaccia utente del modulo del pacchetto Relay seguendo questa procedura:

  1. Fai clic su un file di un pacchetto UI all'interno della cartella ui-package di destinazione.

  2. Se la finestra dello strumento di inoltro non si apre automaticamente, fai clic sull'icona di inoltro per aprirla.

  3. Fai clic sul pulsante Genera file di mappatura in Opzioni pacchetto.

    Genera affordance per il file di mappatura

Nome del file di mappatura

Il nome di un determinato file di mappatura deve corrispondere al nome della cartella del pacchetto UI per il componente sostituito. Pertanto, play_bar.json mappa il pacchetto UI nella ui-packages/mappings cartella a un componente di codice esistente.

Contenuti del file di mappatura

Il file di mappatura contiene le seguenti proprietà:

  • target: (obbligatorio) il nome della funzione composable personalizzata. Per impostazione predefinita, si tratta del nome della funzione creata dal codice generato.

    "target" : "CustomComposableName"
    
  • package: (obbligatorio) nome del pacchetto in cui si trova il composable personalizzato. Per impostazione predefinita, si tratta del pacchetto della funzione creata dal codice generato.

    "package" : "com.example.podcastapp.ui.components"
    
  • generateImplementation: (facoltativo) true o false. Se true, viene comunque creata un'implementazione di questo pacchetto UI nel file di codice generato. Se è false, l'implementazione non viene creata. Per impostazione predefinita, questo valore è true.

    "generateImplementation" : true
    
  • generatePreviews: (Facoltativo) true o false. Se true, nel file di codice generato viene creata un'anteprima del componente personalizzato mappato. Se è false, non viene creata alcuna anteprima. Per impostazione predefinita, questo valore è true.

    "generatePreviews" : true
    

Varianti mappate

Se un componente Figma ha varianti, il composable generato contiene parametri enumerati che codificano la variante (come descritto nel tutorial Gestire le varianti di design). Se vuoi mappare un componente Figma con varianti al codice esistente, deve essere mappato a un composable che accetti gli stessi parametri del composable generato. Ad esempio, per un componente Figma denominato Chip con una variante la cui proprietà è ChipType, la firma componibile generata da Chip è la seguente:

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

Se vuoi che il componente Chip Figma venga mappato a un composable MyChip esistente, la firma di MyChip deve avere la stessa firma del composable generato (supponendo che non siano specificate direttive aggiuntive). A livello concettuale, questo suggerisce che il componente di codice esistente sia in grado di supportare le stesse varianti di design del componente Figma.

Direttive aggiuntive

Ad esempio, se la funzione componibile che vuoi scegliere come target ha la seguente firma:

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

Puoi aggiungere un blocco fieldMappings al file di mappatura che influisce sulla modalità di mappatura dei parametri. In questo caso, contiene una mappatura dal parametro chipText in Chip al parametro description in MyChip.

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

I tipi per il blocco fieldMappings includono:

  • parameter: mappa un campo del pacchetto UI a un parametro di codice.
    • source: nome del parametro specificato nel pacchetto UI.
    • target: nome del parametro specificato nel componente di codice di destinazione.
  • lambda: mappa un campo del pacchetto UI a una funzione lambda dei contenuti.
    • source: nome del parametro specificato nel pacchetto UI.
    • target: nome del parametro specificato nel componente di codice di destinazione.
  • modifier: mappa un campo del pacchetto UI a un metodo di modifica.

    • source: nome del parametro specificato nel pacchetto UI.
    • method: metodo dell'oggetto Modifier che deve essere invocato nel codice generato.
    • parameter: nome del parametro all'interno del metodo Modifier specificato.
    • library: il nome del pacchetto qualificato da importare per accedere al metodo Modifier.
    • scope: uno dei due valori per indicare l'ambito del modificatore:
    • any: il modificatore può essere utilizzato in qualsiasi ambito del ricevitore.
    • relay: il modificatore deve essere utilizzato nell'ambito del ricevitore dell'oggetto RelayContainer di Relay.