将组件映射到现有代码

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

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

Mapped component overview
diagram

这是一个示例

在 Figma 中,设计师创建一个 **卡片** 组件,该组件包含一个 **播放栏** 组件的实例,打包这两个组件,然后将它们发送给开发者。

当开发者从 Figma 导入 UI 包时,会在 ui-packages 中创建两个目录:cardplay_bar。当他们构建项目时,会创建两个可组合函数:CardPlayBar。通常,因为 **卡片** 在 Figma 中包含 **播放栏** 实例,所以在代码中,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** 且其属性为 **ChipType** 的 Figma 组件,**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 对象的接收器作用域中使用。