我正在开发一个UIView
使用多个单独NSLayoutManager
对象呈现文本的自定义。(此视图的文本定位要求超出了内置文本视图类可以支持的范围。)当布局的文本是希伯来语时,我很难为其中一种布局获得正确的垂直位置。对于这篇文章的篇幅,我深表歉意,但我想包含尽可能多的相关细节。
问题
这是我要完成的示例:
“2”的基线与希伯来字母“ו”(以自定义字体呈现)的基线很好地对齐。但是,如果我将“2”的文本切换为希伯来数字(实际上是希伯来字母“ב”,在数字上下文中的值为 2),结果如下(“ב”太高):
这里唯一的变化是文本字符串。而不是"2"
,它是"\u{05b1}"
。我希望一切都在一个共同的基线上,并希望有任何解决问题的建议(这适用于所有希伯来数字,而不仅仅是"\u{05b1}"
)。
编码
(我应该提到,出于技术原因,我不能NSLayoutManager
对数字和正文都使用一个。)我试图通过垂直移动数字的渲染位置通过字体上升的差异来对齐基线。这是计算班次的代码:
numberFont = UIFont.systemFont(ofSize: /* some size */)
offset = fullFont.ascender - numberFont.ascender
这是我NSLayoutManager
为数字创建的方式:
var lbl = "2" // or "\u{05b1}"
let paraStyle = NSMutableParagraphStyle()
paraStyle.alignment = .center
let text = NSTextStorage(
string: lbl,
attributes: [NSFontAttributeName: numberFont,
NSParagraphStyleAttributeName: paraStyle]
)
let layout = NSLayoutManager()
text.addLayoutManager(layout)
let container = NSTextContainer(
size: CGSize(width: /* some fixed width */, height: bounds.height - offset)
)
container.lineFragmentPadding = 0
layout.addTextContainer(container)
let x = ... // irrelevant
let origin = CGPoint(x: x, y: bounds.minY + offset)
后来,我使用以下方法渲染文本:
let range = layout.glyphRange(for: layout.textContainers[0])
layout.drawGlyphs(forGlyphRange: range, at: origin)
正文使用相同的逻辑处理,但没有offset
(当然还有不同的字体)。这对于阿拉伯数字(例如,“2”)非常有效,但对于希伯来数字(例如,“ב”)则无效。
更多信息
对于上面的图像,字体大小 ( .pointSize
) 和 ascent ( .ascender
) 属性是:
尺寸:文本 = 14.3890409469604;数字 = 8.63342465753425
上升:文本 = 16.159567469731;数字 = 8.2203017979452
我还生成了一些关于布局的诊断信息,但这些数字对我来说没有多大意义。这是打印信息的代码:
size = text.size()
mgr = NSLayoutManager()
text.addLayoutManager(mgr)
container = NSTextContainer(
size: CGSize( width: CGFloat.greatestFiniteMagnitude,
height: CGFloat.greatestFiniteMagnitude))
container.lineFragmentPadding = 0
mgr.addTextContainer(container)
mgr.ensureLayout(for: container)
range = mgr.glyphRange(for: container)
print("label:", lbl)
print(" text size:", size)
print(" bounds:", mgr.boundingRect(forGlyphRange: range, in: container))
以下是两个文本(“2”和“\u{05d1}”)的结果:
label: 2
text size: (5.3958904109589, 10.3027782534247)
bounds: (0.0, 0.0, 5.3958904109589, 10.3027782534247)
label: ב
text size: (4.67931616438356, 9.19459726027397)
bounds: (-1.88208657534247, -0.578439452054793, 9.5054005479452, 9.77303671232876)
关于这个让我感到困惑的几件事:
- 希伯来文文本的边界从 x 和 y 的负值开始。负的 x 起源可能与希伯来语是从右到左的脚本有关,但是负的 y 起源呢?
- 报告的布局大小是边界高度和边界的 y 起点或(也许更准确地说)容器中文本的底部的代数和,而不是实际的整体大小。
NSAttributedString.size()
坏了吗? - 这些数字似乎都无法解释“2”和“\u{05d1}”在垂直位置上的视觉差异。