让 iOS macOS 中文字体实现视觉垂直居中

在开发落格输入法 macOS 的时候,我遇到了一个比较奇葩的问题,这个问题一直困扰我到现在——当有些地方需要垂直居中显示一排文字的时候,如何让这些字真正的“居中”?

 

乍看之下这似乎没什么道理,垂直居中嘛……等等,macOS 上的 NSTextField  还真没有办法让你的一行文字垂直居中……🤷‍♂️

第一代方案

后来,我参考网上的一些解决方案,自己动手写了一个 NSTextFieldCell  的子类,这样文本就能真正地实现垂直居中了,代码如下:

 

第二代方案

后来为了提升布局效率,我不再使用 NSTextField ,而是直接在 NSView  上绘制文本,不过原理还是一样的,根据字体视觉居中来设置 y 值偏移量。

但是好景不长,很快,落格输入法就要支持候选栏自定义任意字体了,这下就很糟糕了——因为并不是所有的字体都有着同样的高度,比如同是 18 号大小的中文字,系统字体和系统自带娃娃体字体高度就是不同的:

相比与系统自带,娃娃体明显靠下

你看,同样大小的字号,右侧娃娃体明显比左侧系统自带字体要矮一些——关键是变矮后,他们都是基于字体基准线来排布的,导致娃娃体这个字体在实际视觉中“靠下”了。

事实上类似娃娃体这样的字体有很多,比如宋体、楷体等中文字体几乎全都是不尽相同的低矮设计,这样你就很难找到一个通用的偏移量去垂直居中文字。

第三代方案

这次,既然已经直接绘制文本了,那么我就从字体属性本身下手,查看字体声明,我发现了一个有趣的属性 boundingRectForFont ,这个属性返回一个表示文字字符边界的矩形,这就很有意思了,不同的字,字符的高度不同,边界的高度也就不一样。

所以我在每次布局时都创建一个相同字号的系统字体,获取字体边界,再获取用户自定义的字体的边界,两者取高度差,就是用户字体和系统自带字体的字符高度差了。然后,再根据上文中的思路,调整对应偏移量,即可得到真正的视觉垂直居中布局:

动态计算偏移量后实现任意字体视觉上垂直居中

 

另,有些老字体比如 宋体 就很尴尬,它在同样大小字号下比系统默认字体的矩形还要大,但实际字体大小与系统字体相同,同时字体整体是“底部对齐”,于是差值是负数,结果导致这个字体本身就靠下了,偏移后反而更靠下了……对于这类,我大力出奇迹,直接取绝对值就好了……🤷‍♂️

 

 

 

发布者:R0uter

如非声明,本人所著文章均为原创手打,转载请注明本页面链接和我的名字。

留下评论

电子邮件地址不会被公开。 必填项已用*标注