2023 年 11 月,我们发布了 智能布局的重大升级,在本系列文章中,我们将深入了解我们如何实现它。 在第一篇文章中,团队介绍了背景,并解释了我们如何计划工作。在本篇文章中,他们解释了他们如何着手解决问题,并提高智能布局的可靠性和可预测性。
在制定将智能布局从符号中解放出来并使其在所有地方都可用的计划时,我们知道我们必须使其变得更加智能。
长期以来,我们一直从客户那里听说(并且我们自己也体验过),对使用智能布局的符号进行更改可能会导致某些内容在不应该移动时移动,或者出现相反的情况。更糟糕的是,这种情况可能不一致地发生。
如果我们首先尝试让智能布局在所有地方都可用,然后解决这些问题,我们只会扩大问题发生的范围,并将更多人暴露在这些问题中。这也将使这些问题以后更难修复。
为问题创造更大的表面积,让更多设计和人员受到这些问题(以及我们可能做出的任何进一步更改)的影响,将使期待智能布局改进的客户感到沮丧和失望。这对我们来说是不可接受的,即使这意味着将这些改进推迟一段时间。
识别问题
但这些问题到底是什么?我们有多少个不同的问题?它们何时发生?是什么导致它们发生?我们能否发现它们之下任何共同的根本原因?这需要进行一些侦探工作。
我们开始收集我们积累的许多问题,并逐个仔细检查它们。在每种情况下,我们都会查看来自客户的示例文档,并将它们分解成最基本的要素,识别导致意外问题的因素和步骤。
我们最初作为一个更大的团队开始这项工作;包括来自我们支持团队的同事,以及我们的联合首席执行官(智能布局的最初主要开发人员),以及项目团队中的每个人。这有助于我们通过产品开发中的每个角色建立共同的语言和理解。然后,我们继续以一个更小的团队进行工作,处理了 50 多个问题,并根据严重性和问题领域对它们进行分类。
在经过长时间的彻底调查后,我们发现了一些需要关注的问题领域
- 不同方向之间不一致的规则。正如我们在第一篇文章中提到的,智能布局会查看图层在布局方向上如何重叠。这样,一个左右布局的设计应该与一个左右布局镜像版本的设计工作方式完全相同。但是,情况并非总是如此,这使得该功能的可信度降低。
- 沿着同一轴嵌套布局。设计师可以将智能布局容器相互嵌套,并且智能布局允许我们在彼此之间自由放置图层。这会导致多个智能布局容器并排出现,但在同一个布局轴上有不同的方向的情况。在这些情况下,我们并没有始终尊重这些不同的方向。
- 删除图层时清理空间。从布局中删除图层带来了额外的挑战。我们不仅必须考虑图层本身占用的空间,而且还要考虑它周围的空间,否则设计会留下过多的空间,看起来不对。虽然这种情况确实发生了,但它并不完全符合预期。
除了这些关键领域之外,我们还有一些零散的单个问题,其中一些问题我们认为足够重要,需要单独修复。
建立安全网
智能布局已经存在三年多了,它已成为无数文档和大型团队使用的库的家园。这与它的自由形式排列特性相结合,意味着我们不能简单地开始进行更改——即使这些更改会更好。造成大规模意外副作用的风险实在太高了。
为了确保我们向前迈出两步,而不是后退一步,我们编写了许多性能更高、更易于调试的单元测试。这保证了我们不会无意中撤销当前的任何正确预期。有了这些测试,当我们实现使智能布局更加一致、可预测和更易于理解的更改时,我们可以保持所有内容与设计师可能设置的方式兼容。
在修复每个单独的问题时,我们不仅将原始场景本身输入测试套件,还将针对不同的布局方向,以及相关的和略微不同的布局的变体输入测试套件。在项目结束时,我们最终为智能布局增加了 400 多个额外的单元测试。
深入细节
有了测试套件为更改提供安全网,我们开始逐个解决我们的关键问题领域。我们从跨方向一致的行为问题和具有不同方向的嵌套布局问题开始。这些问题是相辅相成的,这意味着我们可以稍后再解决空间清理问题——这是一个更孤立的问题。
问题领域 1:创建布局一致性,无论方向如何
智能布局的逻辑不会分别处理左右或上下,而是处理图层在任何给定布局方向上是向前还是向后。换句话说,您会期望左右布局的工作方式与镜像版本的左右布局相同。
在左右布局中,重叠被更改图层左边缘(前沿)的图层将保持原样。如果它重叠被更改图层的右边缘(后沿),智能布局将调整它的大小。您会期望这对左右布局来说是相反的,但事实并非如此。在左右布局中,我们总是根据某个东西是在左侧/右侧应用规则,完全忽略了布局方向是相反的。
这是我们必须权衡破坏现有文档中的布局与引入更一致和可预测的行为之间的领域之一。我们选择了后者。现在,我们始终根据布局方向调整大小重叠后沿的图层,并始终将图层移动到后沿之后。
左右布局现在表现得像左右布局的镜像版本
问题领域 2:改进沿着布局轴重叠的图层的布局
我们的第二个关注领域是沿相同布局方向重叠的多层布局。以前,使用智能布局,无法在另一个水平布局内包含水平居中或从右到左的布局。这是一个许多客户遇到的限制,阻止了智能布局的一系列可能性——我们知道我们想要解决它。
请查看下面的示例以了解我们的意思。在这个示例中,我们有一个包含列的表格,其整体布局水平居中。在右列中,我们有一个从左到右布局的单元格。这工作正常。在中间列中,我们有一个从右到左布局的单元格,用于数字,在右列中,一个用于评分的居中布局的单元格。
为了使此示例正常工作,我们必须改进智能布局的逻辑,以计算和调整嵌套布局中各个层的定位,不仅使这种嵌套布局成为可能,而且确保所有内容都出现在您期望的位置。
使这种嵌套布局按您的预期工作涉及三个独立的操作:调整大小、重新定位和移动。
问题领域 3a:消除隐藏层之间的空格
我们要解决的下一个问题领域是,当您隐藏布局内的嵌套符号实例时会发生什么——具体而言,当您执行此操作时,如何消除层之间的空间。在我们之前的实现中,当您隐藏一个层时,我们使用该层之后沿着布局方向的空间来计算其他层的定位和尺寸变化。这导致了两个问题
- 当您沿着布局轴隐藏最后一个层时,在其之后没有沿着布局方向的空间可以使用。并且如果符号内的层具有到符号边界的填充,当您隐藏符号尾部的层时,我们会清除其后的任何空间,但这通常是您希望保留的填充。
- 隐藏堆栈式布局中的第一个和最后一个层时的行为不同,因此更改布局方向会导致不同的行为。这不是我们想要的。
在堆栈式布局中,各层之间有间距,一种解决方案可以是移除您要移除的层前的间距。但是,当您移除两个或多个层时,这种方法就会出现问题。在这种情况下,您需要移除两个层前的间距,以保持间距的一致性。这种行为对于用户来说很难预测,尤其是考虑到不同的布局方向。
相反,我们尝试移除尺寸最小的空格。事实证明,这不仅非常容易实现,而且还具有非常有趣的副作用,即保留了剩余层的相对距离!另外,这也保留了接近的格式塔原则。
下面的示例显示了它的实际应用。这里我们有一个工具栏,其中包含三个项目部分。每个部分之间都有一个较大的间距,而其内的项目之间则有较小的间距。在我们之前的迭代中,我们移除的间距可能位于项目之间或项目外部(取决于您隐藏的项目),这会导致工具栏的显示方式以不可预测的方式发生变化。
现在,通过移除最小的相邻空格,隐藏工具栏组中的单个项目仍然可以保持分组的完整性,而移除组的所有项目仍然可以保持相邻组的分开。更棒的是,这种方法无论布局方向如何,都具有可预测的行为!
隐藏层时移除最小的相邻空格,可以保持这种布局中的正确间距。
问题领域 3b:隐藏层时保留间距
我们对清理多余空间的新方法感到满意,但我们也从客户那里听说,他们的布局依赖于移除特定空间——而且并不总是我们新设置移除的空间。处理这个请求对智能布局的核心原则提出了挑战。
正如我们在第一篇文章中概述的那样,智能布局的核心原则是最小的设置,而是从设计人员设置布局的方式推断意图。当需要额外的控件时,我们更喜欢人们已经知道的选项,例如固定到边缘和固定大小约束。这些已经可用于组内的任何层,但也可以在智能布局的上下文中使用。
我们知道,解决保留特定空间问题的方法是找到一种方法来选择隐藏的层是否保留其空间。我们寻找了一个好的启发式方法来确定何时保留隐藏层的空间,以及设计人员可以使用哪些现有选项来设置它,但没有一个对我们有效。最终,我们决定添加一个新的显式智能布局选项——一个名为“隐藏时保留空间”的复选框——可用于符号实例内的符号。
虽然我们相信有强有力的原则驱动着我们的产品设计理念,但采取非教条主义的方法并保持灵活性非常重要,因为当这种理念开始带来限制时。
有时你只需要发布一个复选框。
发布我们的改进
虽然我们改进和扩展的测试套件让我们确信我们不会以任何方式出现倒退,但我们想确保我们的改进符合设计人员的预期——从我们自己的设计团队开始。
我们在我们夜间使用的 Sketch 版本中将每个领域的工作置于相应的特性标志之后,我们的设计师在日常工作中使用这些特性标志。这样,我们可以公开我们的更改并评估它们的影响。当出现问题时,我们可以切换特性标志以轻松找到罪魁祸首区域——并在我们修复问题时为我们的设计师提供一个逃生通道。
即使有了所有这些安全网,智能布局处理任何排列的能力意味着我们不可能考虑我们客户可能使用的惊人数量的场景。我们知道我们希望尽可能多地将此更新提供给人们,但就像我们在内部做的那样,我们希望为遇到问题的任何人提供一个逃生通道。
我们的第一个想法是在Beta 版本中发布这些更新,但我们的 Beta 版本需要付出努力才能选择加入。相反,我们在Mac 应用程序的 v95中添加了一个新的实验特性设置面板。这使设计人员可以尝试正在开发的特性,通过社区论坛分享他们的反馈,并在需要时将其关闭。我们在更好的智能布局可靠性特性选项下发布了我们的工作,并且知道它可以随时轻松关闭,因此默认情况下启用它,以获得最大的曝光率。
最终,针对此更新的负面反馈很少,很少出现倒退,这正是我们希望看到的。现在,随着智能布局的基础更加稳固,我们终于可以开始着手这个项目的最后也是最受期待的阶段:将智能布局从符号中移除,并将其引入组和画板——但这将是我们下一篇文章的内容。