将组件映射到现有代码

开发者可以通过提供 UI 包和现有代码组件之间的映射来定制代码生成过程,而不是生成代码。当现有实现具有无法通过生成的代码实现的功能(例如动画或复杂行为(例如下拉菜单))时,这将非常有用。

开发者使用映射文件来指定如何映射组件。映射文件至少告诉代码生成器如何到达目标可组合函数,以便可以创建正确的客户端代码。

Mapped component overview
diagram

以下是一个示例

在 Figma 中,设计师创建了一个 **Card** 组件,该组件 包含一个 **Play Bar** 组件的实例,将这两个组件打包并发送给开发者。

当开发者从 Figma 导入 UI 包时,将在 ui-packages 中创建两个目录:cardplay_bar。当他们构建项目时,会创建两个可组合函数:CardPlayBar。通常,因为 **Card** 在 Figma 中包含一个 **Play Bar** 实例,所以在代码中 Card 可组合函数包含对 PlayBar 可组合函数的调用。

但是,设计师和开发者希望 Card 改用现有可组合函数 MyExistingPlaybar,该函数具有难以在 Figma 中描述的功能。因此,开发者添加了一个名为 play_bar.json 的映射文件,该文件将 play_bar UI 包映射到 MyExistingPlaybar

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

现在,当开发者构建项目时,Card 会调用 MyExistingPlaybar 而不是 PlayBar。请注意,MyExistingPlaybar 必须具有与 PlayBar 相同的参数(尽管可能存在一些差异,如下面的 其他指令 中所述)。

映射文件

在您的 Android Studio 项目中,映射文件被添加到 ui-package-resources/mappings 下,位于 ui-packages 文件夹旁边。Relay 在构建期间查找映射文件。

Mapping file in the project
view

生成映射文件

Relay 可以为任何导入的 UI 包生成映射文件。请按照以下步骤操作

  1. 右键单击目标 ui-package 文件夹中的包文件夹或任何文件。选择 **生成映射文件**。

    Generate mapping file
affordance

  2. 在对话框中配置以下选项

    Dialog for generating mapping
files

    • **文件位置:** 设置生成的映射文件的位置。

    • **目标可组合函数:** 设置用于代替生成的可组合函数的自定义可组合函数。您可以选择使用现有可组合函数或从对话框中创建新的可组合函数。创建新的可组合函数会在 UI 包中定义的参数的基础上创建一个可组合函数。

    • **生成的文件:** 在映射文件中设置 generateImplementationgeneratePreview 选项。有关详细信息,请参见下面的 映射文件内容
  3. 单击 **生成映射文件**。一个新的映射文件将在 ui-package-resources/mapping 文件夹中创建,其中包含指定的配置。

您也可以使用以下步骤从 Relay 包模块 UI 中打开 **生成映射文件** 对话框

  1. 单击目标 ui-package 文件夹中的 UI 包的任何文件。

  2. 如果 Relay 工具窗口没有自动打开,请单击 Relay 图标以打开窗口。

  3. 单击 **包选项** 下的 **生成映射文件** 按钮。

    Generate mapping file
affordance

映射文件名

给定映射文件的名称必须与它替换的组件的 UI 包文件夹的名称匹配。因此,play_bar.jsonui-packages/mappings 文件夹中的 UI 包映射到现有代码组件。

映射文件内容

映射文件包含以下属性

  • **target:** (必需)自定义可组合函数的名称。默认情况下,此名称是生成代码创建的函数的名称。

    "target" : "CustomComposableName"
    
  • **package:** (必需)自定义可组合函数所在的包的名称。默认情况下,此名称是生成代码创建的函数的包的名称。

    "package" : "com.example.podcastapp.ui.components"
    
  • **generateImplementation:** (可选)true 或 false。如果为 true,则在生成的代码文件中仍然会创建此 UI 包的实现。如果为 false,则不会创建实现。默认情况下,此值为 true。

    "generateImplementation" : true
    
  • **generatePreviews:** (可选)true 或 false。如果为 true,则会在生成的代码文件中创建映射的自定义组件的预览。如果为 false,则不会创建预览。默认情况下,此值为 true。

    "generatePreviews" : true
    

映射的变体

如果 Figma 组件具有变体,则生成的可组合函数包含枚举参数,这些参数对变体进行编码(如 处理设计变体 教程中所述)。如果您要将具有变体的 Figma 组件映射到现有代码,则必须将其映射到与生成的可组合函数采用相同参数的可组合函数。例如,对于名为 **Chip** 的 Figma 组件,其变体的属性为 **ChipType,Chip** 的生成的可组合函数签名如下所示

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

如果您希望 Chip Figma 组件映射到现有的 MyChip 可组合函数,则 MyChip 的签名必须与生成的可组合函数的签名相同(假设没有指定 其他指令)。从概念上讲,这表明现有代码组件能够与 Figma 组件具有相同的设计变体。

其他指令

例如,如果您要定位的可组合函数具有以下签名

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

您可以将 fieldMappings 块添加到映射文件中,以影响参数的映射方式。在本例中,它包含从 Chip 中的 chipText 参数到 MyChip 中的 description 参数的映射。

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

fieldMappings 块的类型包括

  • parameter:将 UI 包字段映射到代码参数。
    • source:UI 包中指定的参数的名称。
    • target:目标代码组件中指定的参数的名称。
  • lambda:将 UI 包字段映射到内容 lambda。
    • source:UI 包中指定的参数的名称。
    • target:目标代码组件中指定的参数的名称。
  • modifier:将 UI 包字段映射到 修饰符 方法。

    • source:UI 包中指定的参数的名称。
    • method:在 Modifier 对象上应在生成的代码中调用的方法。
    • parameter:指定 Modifier 方法中的参数的名称。
    • library:用于访问 Modifier 方法的限定包名称。
    • scope:两个值之一,用于指示 Modifier 的作用域
    • any:修饰符可以在任何接收器作用域中使用。
    • relay:修饰符必须在 Relay 的 RelayContainer 对象的接收器作用域中使用。