在中继的引擎盖下,Android Studio插件用于导出无花果组件以组成
#kotlin #android #组成 #figma

最近,Google宣布了Relay,这是一个新的过程,允许团队在无花果中创建UI并生成高保真构成的UI组件。它目前处于Open Alpha中,可以作为Android Studio的插件安装。这是一个非常有趣的工具,它会根据您选择从FIGMA导出的组件自动生成撰写代码。关于它的作用以及如何运行here的概述,但是您可能会问:引擎盖下到底发生了什么?因此,让我们详细介绍从无花果的过程中使用继电器撰写代码。

注意:这不是无花果的教程,而只是查看生成的代码以及与自定义撰写代码的比较。

注意:继电器是一个新的且不断发展的库,因此其中一些发现可能会在将来发生变化。作为参考,我正在测试继电器版本“ 0.3.00”。

步骤1.无花果

对于此博客,我制作了一个带有简单组件的Figma页面,一个按钮。

Image description

此按钮有些简单,它是矩形形状,文本为子视图。它已作为组件导出,并在其设计中定义了一些属性。

Image description

如果您不熟悉无花果,那很好。这是要指出的主要内容:

按钮:

  • 半径为15
  • 具有10
  • 的外部填充
  • 是中央对齐的
  • 您的颜色为 primary *

其中大多数是直截了当的属性,要注意的是颜色,在无花果中定义为颜色样式,因此可以重新使用。

文字:

  • 填充按钮
  • 具有按钮的版式*
  • 有一个定义的内容(文本)
  • 文本都以水平和垂直为中心
  • 具有主文本的颜色

大多数事情都很直截了当,但值得注意的是,文本样式按钮在无花果中定义。它包含字体名称,样式和大小(以及一些间距)。

看起来不错(我希望!),让我们导出它,看看我们在Android Studio中获得的内容。

步骤2. UI软件包

Image description

在Android Studio中,我们将此按钮作为UI包装导入。在这里,我们可以看到一些小文件,例如文本文件和配置文件。我们还看到一个font文件夹,其中包含按钮中使用的字体的所有变体,这很有趣。 默认中继将所有字体放入每个UI包装中,即使它们在组件之间共享。,如果您有两个组件(例如一个按钮和文本字段),并且它们都使用相同自定义字体,然后继电器将在您的项目中添加两个相同字体的副本,而不是引用一个副本。使用共享字体有一个实验功能,但这超出了本文的范围。

让我们看一下JSON文件。在这里,我们可以看到我们定义的所有内容。组件的每个部分都有其自己的名称和ID,并在“原子”中定义(这似乎与Atomic Design的概念保持一致)。然后,在“模式”中,我们可以看到来自无花果的所有属性。

{
  "name": "button_primary",
  "source-key": { ... },
  ...,
  "design": {
    "atoms": [
      {
        "type": "group",
        "id": "top_level",
        "root": "true"
      },
      {
        "type": "text",
        "id": "buttonText"
      }
    ],
    "modes": {
      "Button/Primary": {
        "rules": [
          {
            "id": "top_level",
            ...
          },
          {
            "id": "buttonText",
            ...
          }
        ]
      }
    }
  }
}

这是一个大文件,所以我将其分解为清晰。我们可以看到我们有两个原子,以及与原子相关的一系列规则。

{
  "id": "top_level",
  "padding": "10.0",
  "border-radius": "15.0",
  "main-axis-align": "start",
  "cross-axis-align": "start",
  "children": ["buttonText"],
  "item-spacing": "10.0",
  "background-color": {
    "alpha": "1.0",
    "hue": "38.82352941176471",
    "saturation": "1.0",
    "value": "1.0"
  },
  "clip-content": "false"
}

首先,我们可以看到该层已重命名为“ top_level”,这很有意义,但看起来很奇怪。它具有填充,边界 - 拉迪乌斯,对齐和颜色。
我们看到颜色“主”已设置为HSV颜色,没有提及颜色样式。再次有了实验功能,我们也许可以获得这种颜色样式,但现在是一种原色。

{
  "id": "buttonText",
  "size-constraints": {
    "width-constraints": {
      "sizing-mode": "proportional",
      "value": "1.0"
    },
    "height-constraints": {
      "sizing-mode": "proportional",
      "value": "1.0"
    }
  },
  "font-weight": "700.0",
  "color": {
    "alpha": "1.0",
    "hue": "38.4375",
    "saturation": "1.0",
    "value": "0.25098039215686274"
  },
  "text-content": "Test Text",
  "overflow": "visible",
  "max-lines": "-1",
  "text-align-vertical": "center",
  "line-height": "1.25",
  "typeface": "Quicksand"
}

buttontext可以保留其名称,在这里我们可以看到它具有尺寸约束,颜色,文本内容,对齐和字体。

在这里,我们看到我们在无花果中设置的字体已经消失了。取而代之的是,我们具有字体的名称,字体重量而不是样式以及线高。奇怪的是,字体的大小没有出现。这不是最糟糕的,但确实有些混乱。

好!我们已经导入了JSON配置,现在我们可以构建它并查看我们生成的撰写代码!

步骤3.生成的代码

@Composable
fun ButtonPrimary(
    modifier: Modifier = Modifier,
) {
    TopLevel(
        modifier = modifier
    ) {
        ButtonText(modifier = Modifier.rowWeight(1.0f).columnWeight(1.0f))
    }
}

在这里,我们可以看到看起来像是直截了当的构成功能,并从JSON定义了原子。但是这些高级和buttontext功能是什么?好吧,您可以想象,这篇文章的代码太多了,因此,简而言之,我将突出一些关键点。如果您想深入研究生成的内容,我创建了一个包含生成代码的github gist here。现在让我们介绍一些值得注意的代码。

继电器包装纸

从继电器生成的所有代码都将函数包裹在前缀中继中。例如,ButtonText函数包含RelayText函数,该函数采用无花果中定义的属性。这些包装器功能是在relay-runtime软件包中生成的,而我们的特定按钮是在relay软件包中定义的。

这甚至到拥有RelayColumnRelayRow,奇怪的是不包裹他们的作曲。

特性

这些包装器中的属性具有与无花果中提到的相同的名称,而不是撰写名称。例如,我们有mainAxisAlignment,而不是horizontalArrangement。同样,尽管继电器试图使用尽可能多的通用类型(即浮动,布尔值等),但它并不总是使用撰写类型。它可以做一些类型的颜色,输水等等,但避免了其他类型的AlignmentTextDecoration。我敢肯定有这样的技术原因,但确实确实使它感觉像是生成的插件。

转换

转换很有趣,尽管有点混乱。许多转换只是when语句,将无花果变量与组成变量进行比较。大多数转换直接在组合函数中,而不是具有扩展或组织代码更多。一般而言,对于整个生成的代码来说,它有点混乱且难以阅读,但是完成工作。

奖金:与典型代码相比

现在,我们已经看到了生成的代码的外观以及如何到达那里,我决定将其与我个人创建此组件的方式进行比较会很有趣。以下是我的版本:

Button(
  onClick = { /*TODO*/ },
  modifier = Modifier.fillMaxWidth(1.0f),
  shape = RoundedCornerShape(15.dp),
  elevation = ButtonDefaults.elevation(defaultElevation = 0.dp),
  colors = ButtonDefaults.textButtonColors(backgroundColor = DesignColors.primary),
) {
  Text(
    text = text,
    style = typography.button,
    color = DesignColors.onPrimary,
    modifier = Modifier.padding(10.dp),
  )
}

在这里,我正在使用基本的喷气背包组件,并增加了创建文本和颜色样式以重复使用。

有趣的是看到开发人员可能会产生的差异与继电器的生成之间的差异。如果您经过包装器和名称更改,则两个功能最终都在调用相同的代码。即使您必须更深入地看到它,均使用RoundedCornerShapepaddingelevation。唯一有趣的区别是继电器不使用Composobable ButtonText功能,而是坚持自己的自定义实现。当无花果没有按钮之类的android组件的概念时,这是可以预料的。

所以,是的,您可以看到,尽管不同,但它们都使用相似的代码。当然,我的代码更加简洁,更易于阅读,但是如果没有开发人员要手动更新可组合的问题真的很重要吗?

结论

所以这就是接力赛引擎盖下的情况!不幸的是,有些事情我没有时间覆盖,例如嵌套组件(扰流板,它们按预期工作!),在无花果中添加自定义参数,绘制样式的作曲和向量。如果这些是您希望我涵盖的话题,请在评论中知道。另外,如果您有任何疑问或希望看到更多的代码留下评论或在我的twitterdev.toKotlin Slack上与我联系(全部在@kevinschildhorn下)。