了解界面软件包和生成的代码

界面软件包

界面软件包是一种交换界面信息的全新灵活方式。设计人员使用 Relay for Figma 插件,借助 Figma 中的组件创建界面软件包。这样做,即表示设计已准备就绪,可供开发者使用。然后,设计人员向开发者提供其 Figma 设计文件的网址。

开发者使用 Android Studio 插件从 Figma 设计文件导入界面软件包。在 Android Studio 项目中,界面软件包包含导入的 Figma 组件的声明性说明以及关联的资源,包括字体文件、图片和 SVG。

界面软件包是持久性工件,可以提交到源代码控制系统。当开发者在 Android Studio 项目中导入 Figma 软件包时,文件会添加到项目的 ui-packages 文件夹内。以下是导入的界面软件包的示例:

<ph type="x-smartling-placeholder">
</ph> 界面软件包的内容

使用导入的界面软件包的项目包含以下文件:

  • [component_name].json - 一个描述组件的 JSON 文件(例如 story_card.json)。
  • config.json - 用于存储特定界面软件包的元数据。
  • fonts/ - 一个存储组件使用的字体资源(如果有)的文件夹。
  • *.png - 组件中使用的图片素材资源(如果有),例如 menu.png
  • [component_name]_preview.png - 组件的预览图片(适用于 示例 story_card_preview.png)。
  • *.svg - 组件中使用的矢量图形资源(如果有),例如三角形。
  • FONTS.txt - 使用的字体(如果有)的列表。
  • DEPS.txt - 任何子组件的名称。
  • VERSION.txt - 用于创建和导入界面的 Relay 版本 软件包。

这些文件存储在 src/main/ui-packages/[package_name] 下。

移除界面软件包

如需从项目中移除界面软件包,您可以删除 ui-packages/ 下的文件夹。移除文件夹后重新构建项目,会同时移除其生成的代码。

生成的代码文件夹结构

在项目构建时,这些界面软件包会转换为生成的代码,其中包含开发者可以调用的 @Composable 函数。这些代码存储在 build/generated/ 下。在“Android”视图中,这些代码在模块目录(在本例中为 app 目录)下显示为 java (generated)res

Android Studio 中包含生成的文件的文件夹

以下屏幕截图展示了此目录中的文件:

  • 字体和图片等资源会复制到 build/generated/res/relay/

    res 文件夹下的生成的资源
  • 每个界面软件包都有生成的代码,位于 build/generated/source/relay/ 下。每个界面软件包的生成的代码文件夹都有 与导入的组件对应的单个文件。它还 包含以 Fonts.kt 结尾的单个文件,该文件包含对 组件使用的字体资源

    java(generated) 文件夹下的生成的 Kotlin 文件
  • 此外,还有一个运行时库 com.google.relay.compose,它提供生成的代码所使用的功能。

    Relay 运行时库

生成的代码结构

可组合项

Figma 中的组件由多个层组成。例如,以下设计包含一个帧层 Hello Card,该帧层包含两个子层:Image(图片层)和 Title(文本层):

包含 Image 层和 Title 层的 Hello Card 组件

在将这种设计转换为代码时,我们会为每个层创建单独的可组合函数,其中 Figma 层的名称是可组合函数的名称(已修改,以符合 Kotlin 语法)。这些层的转换如下所示:

  1. Hello Card 层:

    @Composable
    fun HelloCard(
      modifier: Modifier = Modifier,
      title: String
    ) {
      TopLevel(modifier = modifier) {
          Image()
          Title(title = title)
      }
    ]
    
  2. Image 层:

    @Composable
    fun Image(modifier: Modifier = Modifier) {
      Image(...)
    }
    
  3. Title 层:

    @Composable
    fun Title(
      title: String,
      modifier: Modifier = Modifier
    ) {
      Text(...)
    }
    

经过转换的 Figma 变体和参数

如果 Figma 组件有多个变体,生成的代码会为每个变体属性添加一个枚举。每个变体枚举中的值都对应于该变体属性的值。该可组合项包含每个变体枚举的参数。

// Design to select for NewsCard
enum class View {
    HeroItem,
    ArticleItem,
    AudioItem
}

/**
 *   This composable was generated from the UI Package 'news_card'.
 *   Generated code; do not edit directly
 */
@Composable
fun NewsCard(
    modifier: Modifier = Modifier,
    view: View = View.HeroItem,
    onNewsCardTapped: () -> Unit = {},
    thumbnail: Painter,
    headline: String,
    author: String,
    date: String,
    onMenuTapped: () -> Unit = {}
) {
       when (view) {
           View.HeroItem -> TopLevelViewHeroItem(...) {
               ContentViewHeroItem { ... }
           }
           View.ArticleItem -> TopLevelViewArticleItem(...) {
               ContentViewArticleItem { ... }
           }
           View.AudioItem -> TopLevelViewAudioItem(...) {
               ContentViewAudioItem { ... }
           }
       }
   }
}

Figma 组件的每个内容参数和交互处理程序都会转换为可组合项的参数。下面的 NewsCard 可组合项有四个内容参数(一个图片和三个字符串)和两个交互处理程序(最后两个参数)。

/**
 *   This composable was generated from the UI Package 'news_card'.
 *   Generated code; do not edit directly
 */
@Composable
fun NewsCard(
    modifier: Modifier = Modifier,
    view: View = View.HeroItem,
    thumbnail: Painter,
    headline: String,
    author: String,
    date: String,
    onNewsCardTapped: () -> Unit = {},
    onMenuTapped: () -> Unit = {}
) {...}