iOS14下UILabel显示NSAttributedString末尾下划线超出文本问题
问题描述
带自定义属性的NSMutableAttributedString在iOS12及更早版本的UILabel中显示正常,但在iOS14上出现显示异常:
文本「bukskin」设置了前两个字母为红色、最后4个字母添加下划线,该配置在iOS12上显示完全符合预期:
在iOS14上,下划线会超出单词末尾约两个字符的长度,该问题仅在下划线位于字符串末尾时出现:
分别导出iOS12和iOS14下的字符串属性dump,二者属性配置完全一致,但iOS14下UILabel的实际渲染效果存在差异。
iOS12属性dump(通过enumerateAttributesInRange导出)
word=bukskin attributed_word=b{ NSColor = "UIExtendedSRGBColorSpace 0.8125 0 0 1"; NSLigature = 0; NSUnderline = 0; }uk{ NSColor = "UIExtendedGrayColorSpace 0 1"; NSLigature = 0; NSUnderline = 0; }s{ NSColor = "UIExtendedGrayColorSpace 0 1"; NSLigature = 0; NSUnderline = 1; }k{ NSColor = "UIExtendedSRGBColorSpace 0.8125 0 0 1"; NSLigature = 0; NSUnderline = 1; }in{ NSColor = "UIExtendedGrayColorSpace 0 1"; NSLigature = 0; NSUnderline = 1; } attrs={ NSColor = "UIExtendedGrayColorSpace 0 1"; NSLigature = 0; NSUnderline = 1; }
iOS14属性dump
word=bukskin attributed_word=b{ NSColor = "UIExtendedSRGBColorSpace 0.8125 0 0 1"; NSLigature = 0; NSUnderline = 0; }uk{ NSColor = "<UIDynamicSystemColor: 0x600003682440; name = labelColor>"; NSLigature = 0; NSUnderline = 0; }s{ NSColor = "<UIDynamicSystemColor: 0x600003682440; name = labelColor>"; NSLigature = 0; NSUnderline = 1; }k{ NSColor = "UIExtendedSRGBColorSpace 0.8125 0 0 1"; NSLigature = 0; NSUnderline = 1; }in{ NSColor = "<UIDynamicSystemColor: 0x600003682440; name = labelColor>"; NSLigature = 0; NSUnderline = 1; } attrs={ NSColor = "<UIDynamicSystemColor: 0x600003682440; name = labelColor>"; NSLigature = 0; NSUnderline = 1; }
问题原因
这是iOS13及以上系统UILabel富文本渲染的已知底层bug,和属性配置无关:
iOS12及更早版本的下划线绘制严格匹配设置的字符范围,iOS13之后系统对末尾带下划线属性的富文本做了多余的绘制延伸,会默认把下划线一直绘制到当前行的末尾空白区域,只有当下划线属性出现在整个字符串的末尾时才会触发该问题。两端导出的属性完全一致也验证了问题出在系统渲染层,不是代码配置错误。
修复方案
可以根据业务场景选择以下任意一种方案:
- 最低成本兼容方案:在富文本末尾拼接一个零宽空格
\u200B,并给这个额外添加的字符单独设置NSUnderlineStyleNone属性,即可截断系统的自动延伸逻辑,零宽空格不会占用视觉宽度,也不会影响原有排版 - 如果不需要适配动态字体:直接关闭UILabel的
adjustsFontForContentSizeCategory开关,大部分场景下也可以解决该渲染异常 - 复杂场景方案:如果以上两种方案都不符合需求,可以改用UITextView展示该富文本,UITextView的富文本渲染逻辑不存在这个bug;也可以通过CoreText/TextKit自行控制下划线的绘制范围,完全规避系统渲染问题
内容的提问来源于stack exchange,提问作者RickJansen
相关产品推荐
相关产品推荐

