iOS UILabel并避免使用自定义字体

时间:2018-03-29 05:16:25

标签: ios fonts uilabel diacritics clipping

首先,StackOverflow上有很多问题,但没有一个完全回答这个问题。

问题主要是,但很可能不仅限于使用UILabel的text属性使用自定义拉丁语字体呈现时的泰语和阿拉伯语变音符号。这在自动布局中也具有内在大小。我已经完成了Apple建议的所有内容,使用文档中提到的设置,WWDC视频以及StackOverflow上的问题(例如clipsToBounds = NO等)。请记住,我的场景中只有我的自定义字体设置剪辑,而不是iOS系统字体(.SF-UIDisplay),甚至iOS系统也没有提供Helvetica或Helvetic Neue。自定义字体已经过检查和重新检查,在这一点上得出结论,iOS是所有平台的异常,甚至是macOS。为了更清楚,使用SF Pro可以看到与自定义字体相同的剪切行为,这是Apple自己在这里提供的字体:https://developer.apple.com/fonts/

这个问题是关于最合适,最少侵入性和最完整的方法来做不必修改变音符所必需的方法。意思是,你如何从头开始做到这一点。

我所有的字体研究和测试运行都让所有参与此问题的人都相信Apple已经在UILabel中专门针对他们的系统字体实施了特殊处理,以避免变音剪辑。所以做出这个假设,我也假设字体没问题,我正在寻找不涉及编辑字体的解决方案。

在我尝试使用该字体时,首先出现的问题是垂直剪切泰国字形的上升变音符号:

นื้ทั้มูHello

这意味着Thonburi字体从自定义拉丁文字体级联时的字形。从这一点来看,修复是使用仅适用于没有任何拉丁字符的泰语的自定义字体,因此可以将其定义为主要字体,并级联到前面提到的仅限拉丁语的自定义字体。在这之后,自定义泰语字体仍然在文本末尾的变音符号上存在水平剪切问题:

Worldฟล์

所以现在我对字体管理木偶可以做的任何事情都感到茫然(尽管仍然接受建议),我正在进行更多以代码为中心的修复。我已经看到了很多提及子类UILabel的问题和答案,但是我想知道这可以实现我所描述的内容。

我也想知道如果选择退出UILabel,对任何人来说都是一种选择。意思是用TextKit从头开始写一些东西是值得的,以避免所有这些似乎只困扰iOS,特别是UILabel的错误。

3 个答案:

答案 0 :(得分:0)

我试图用阿拉伯语的变音符号解决类似的问题,并且找到了解决方法:

我有一个带有UILabel和阿拉伯文字的UITableViewCell,有时它的变音符号被剪掉了

我重写了get_tweets以便直接在UITableViewCell上绘制NSAttributedString

我也减小了- (void)drawRect:(CGRect)frame以便在标签位置的顶部进行手动绘制,但仍然保留它来计算单元格的高度

self.arabicLabel.alpha = 0.1;

答案 1 :(得分:0)

iOS 的核心问题是字体替换。您指定的是拉丁字体,该字体不包含将要渲染的字符的字形,系统使用不同的字体来绘制字形,但它仍然基于原始字体进行测量。

选项 1 是最可靠的选项,它是手动选择包含要呈现的字符的字形的字体。当分配给 UILabel 的字体或其渲染的属性字符串包含将要渲染的所有字形,并且该字体与大多数系统字体一样具有良好的度量时,则不会剪切任何内容。

选项 2,使用字形边界手动测量字符串。创建 UILabel 的子类并覆盖 textRectForBounds 和可能的 drawText。用 .usesDeviceMetrics 测量字符串。这比通过字体度量来衡量要慢,并会产生不同的结果。例如,字符串“a”和“A”的测量方式不同。

选项 3,使用基线偏移和行高倍数为被剪裁的变音符号腾出空间。为每种语言的每种字体选择或计算常量值,并将这些值应用到 UILabel 的属性字符串。这可以补偿您选择的字体与实际呈现字形的字体之间的字体度量差异。我们已经本地化了每种语言的最坏情况下剪切字符的字符串,并使用这些来计算偏移量和高度。不同的字体有不同的最坏情况剪切字符。

答案 2 :(得分:-1)

起初,我认为这是框架方面的问题,但不是,这只是字体指标的严格实施。在除了Web /应用程序开发之外的所有事物中,字体的呈现方式都不那么严格,这就是为什么这个问题很少(如果有的话)出现的原因。字体具有许多指标,可以告诉程序如何在屏幕上呈现它,最重要的是如何处理填充。例如,UILabel(以及UITextField等)将严格应用这些指标。问题在于某些字体的装饰性很强,通常太粗或太斜而无法完美地适合每个字符必须适合的方形画布(尤其是带有重音符号(如变音符号)的情况)。在网络/应用程序开发之外,这不是问题,因为当角色无法适应其画布时,例如非常粗,宽且倾斜的W,程序无论如何都会显示它,这就是为什么低悬的g可能会溢出到其下方的行中。但是,如果该g是用单行UILabel呈现的,则由于iOS中的字体指标实施非常严格,因此会简化低手g的内容。

在进一步研究中,将UILabel子类化(对于UILabel而言)并覆盖其intrinsicContentSize以添加一些额外的填充不是一个好主意。首先,它有点hacky,但更重要的是,它在调试器中产生约束警告。真正的解决方法,而IMO唯一的解决方法是编辑字体的度量标准。

下载像字形(https://glyphsapp.com/)这样的程序,打开字体,打开Font's Info,然后在Masters选项卡中,为字体提供正确的升序和降序值。为了最好地了解这些值的工作原理,请在程序中打开San Francisco字体,然后查看Apple的工作方式(请记住,这是他们专门为macOS和iOS开发制作的字体)。附带说明一下,如果您使用此应用,则在编辑字体信息时,也请进入Features标签,删除所有功能(使用左下方的减号图标),然后点击{ {1}},让程序为您管理字体的功能。

最后一个障碍是裁剪上升和下降指标无法解决的前沿(而不是顶部和底部)。您可以使用Glyphs程序来编辑单个字符的画布大小,以确保它们都适合,但是这会改变字体的外观,因为它会显着改变字符间距。对于这个问题,我认为最好的解决方案是简单地将属性字符串用于标签和文本字段。这是因为属性字符串使您可以安全地编辑填充(而不会破坏内部大小)。一个例子:

Update

为方便起见,我扩展了someLabel.attributedText = NSAttributedString(string: "Done", attributes: [NSAttributedString.Key.font: UIFont.blackItalic(size: 26), NSAttributedString.Key.foregroundColor: UIColor.black, NSAttributedString.Key.paragraphStyle: NSMutableParagraphStyle.kItalicCenter]) ,因为我一直使用此字体:

NSMutableParagraphStyle

此标签会将字体向前推两点,以防止剪切。