提问人:Darumar 提问时间:11/16/2023 最后编辑:Darumar 更新时间:11/16/2023 访问量:18
UILabel 垂直文本对齐以匹配 Figma 设计
UILabel vertical text alignment to match Figma design
问:
我之前已经解决了创建 Figma 设计的像素完美表示的挑战,但事实证明,对齐文本非常困难。我最终得到了一个有效的解决方案,但我对此不太满意。现在我再次面临挑战,希望能得到一些意见,以更好的方式解决这个问题。
我很惊讶,几乎震惊了,这太难了,让我解释一下。
要求
- 我应该能够完全按照 Figma 中的文本样式设置样式。这应该相当容易,因为 Figma 实际上输出了要使用的 NSAttributed 字符串属性,但正如我们将看到的,它不会产生准确的设计。
UILabel
- 当我在Figma中放置一个与文本框相同的距离时,与屏幕顶部的距离相同。文本的垂直对齐方式或基线在设备/模拟器上应与在 Figma 中完全相同。
UILabel
- 应支持并允许文本根据用户在设备设置中的文本大小设置而增长。使用默认的动态类型设置,文本应与 Figma 中的文本完全相同。
UILabel
Dynamic Type
问题
据我所知,根本不可能让香草表现得像我上面概述的那样。这是在花了大约一周的时间探索别人所做的事情并尝试了许多不同的方法之后。我很高兴被证明是错的。UILabel
主要问题是,一旦使用的文本样式修改了基本字体的行高,Figma 中的文本框和文本框就不会以相同的方式布局文本。一旦您将 UX 添加到项目中,就会发生这种情况。他们将开始摆弄文本样式、调整行高、字距、粗细等。UILabel
在 Figma 中对字体行高的任何调整都会将您带入领域,而 Figma 本身建议您使用 .问题是,一旦你开始描述一种字体,字体的布局不再类似于 Figma,我就无法找到替代方法,满足我上面概述的要求。NSAttributedString
lineHeightMultiple
lineHeightMultiple
Figma 在这里有一篇关于他们最近对文本布局的更改的非常好的文章。
简而言之,文本现在在其文本框中布局并居中。只要您不调整 or ,这就是 a 的正常行为方式,这是控制字体行距的两种主要方式。UILabel
lineHeightMultiple
lineSpacing
左边是 Figma 中的设计。我使用的是 Verdana,尺寸 16,线高 150%。旁边的灰色背景框是 Figma 自己关于如何实现这种布局的建议。在中间,我使用的方法,在右边的方法。如您所见,这两种方法都存在问题。lineHeightMultiple
lineSpacing
lineHeightMultiple
尽管这种方法准确地反映了两行文本之间的距离,但它本身的文本在文本框/UILabel 中的布局并不相同。如前所述,Figma 将文本布置在文本框的中间,而 ,在使用 时会在每行文本上方添加额外的空格。这意味着文本被“推”下到内部,并垂直对齐偏离中心。UILabel
lineHightMultiple
UILabel
行间距
此外,我们得到了两行文本之间的准确距离,但这里省略了第一行和最后一行文本上方和下方的间距,这意味着最终变得小于 Figma 中相应的文本框。lineSpacing
UILabel
另请参阅此处的比较
这两种方法都会导致布局不能准确反映 Figma 中的设计,除非您引入其他措施。
溶液
上述两种方法都可以解决,但解决方案并不令人满意,并且有自己的一系列问题。
lineHeightMultiple
由于问题在于文本与 Figma 相比偏离中心对齐,因此这里的解决方案是将 嵌入到容器视图中,并调整其 y 轴位置以使文本在容器视图中居中。由于额外的行高是在文本行上方添加的,因此我们可以按如下方式计算偏移量:UILabel
let yOffset = ((lineHeightMultiple * lineHeight) - lineHeight) * 0.5
其中,如果字体的行高。如果你支持动态类型,你需要在更改时调整它,方法是挂接到 a 的方法并使用缩放字体的 。lineHeight
preferredContentSizeCategory
traitCollectionDidChange
UIVIew
lineHeight
这样一来,我最终得到了以下内容,其中蓝色代表容器,然后我将将其用于布局,文本标签(红色)在其中偏移。
这是我过去一直在使用的解决方案,但除了远非吸引人之外,它也没有很好地解决风格标签的挑战。在这种情况下,UIKit 将缩小字体以适应可用空间,但是缩小字体的实际大小不容易获得,因此很难正确调整 Y 偏移量。adjustsFontSizeToFitWidth
行间距
行距方法的解决方案与此类似,但需要在容器视图和内部标签之间添加正确数量的填充,以达到相同的效果,即容器中文本居中。我不会进一步详细说明这一点,而只是链接到 Mick F 关于该主题的一篇精彩文章。
替代解决方案
使用 和maximumLineHeight
minimumLineHeight
我在 Geri Borbás 的一篇精彩文章中提到的另一种方法是通过计算和设置将标签的行高强制为固定大小,并使其大小相同。但是,此方法不支持动态类型,但如果不需要支持字体缩放,则此方法可能是一种解决方案。maximumLineHeight
minimumLineHeight
用baseLineOffset
从表面上看,这听起来像是要走的路,但根据我的经验,我无法让它给出准确的结果。似乎将 的值添加到字体中,这再次没有给出预期的结果。baseLineOffset
baseLineOffset
lineHeight
帮助?
目前,这是我添加的地方。如上所述,我有两个解决方案,这两个解决方案都会花费我很多方法来解决问题,这可能是我将再次结束的地方。然而,令我惊讶的是,事实证明,做一些对大多数应用程序开发人员来说应该相当普遍的事情是如此困难。除了深入研究我所遗漏的问题之外,还有其他解决方案吗?CoreText
答: 暂无答案
评论