讓 iOS macOS 中文字體實現視覺垂直居中

在開發落格輸入法 macOS 的時候,我遇到了一個比較奇葩的問題,這個問題一直困擾我到現在——當有些地方需要垂直居中顯示一排文字的時候,如何讓這些字真正的“居中”?

 

乍看之下這似乎沒什麼道理,垂直居中嘛……等等,macOS 上的 的NSTextField 還真沒有辦法讓你的一行文字垂直居中……🤷‍♂️

第一代方案

後來,我參考網上的一些解決方案,自己動手寫了一個 NSTextFieldCell 的子類,這樣文本就能真正地實現垂直居中了,代碼如下:

 

第二代方案

後來為了提升佈局效率,我不再使用 的NSTextField ,而是直接在 的NSView 上繪製文本,不過原理還是一樣的,根據字體視覺居中來設置 y 值偏移量。

但是好景不長,很快,落格輸入法就要支持候選欄自定義任意字體了,這下就很糟糕了——因為並不是所有的字體都有著同樣的高度,比如同是 18 號大小的中文字,系統字體和系統自帶娃娃體字體高度就是不同的:

相比與系統自帶,娃娃體明顯靠下

你看,同樣大小的字號,右側娃娃體明顯比左側系統自帶字體要矮一些——關鍵是變矮後,他們都是基於字體基準線來排布的,導致娃娃體這個字體在實際視覺中“靠下”了。

事實上類似娃娃體這樣的字體有很多,比如宋體、楷體等中文字體幾乎全都是不盡相同的低矮設計,這樣你就很難找到一個通用的偏移量去垂直居中文字。

第三代方案

這次,既然已經直接繪製文本了,那麼我就從字體屬性本身下手,查看字體聲明,我發現了一個有趣的屬性 boundingRectForFont ,這個屬性返回一個表示文字字符邊界的矩形,這就很有意思了,不同的字,字符的高度不同,邊界的高度也就不一樣。

所以我在每次佈局時都創建一個相同字號的系統字體,獲取字體邊界,再獲取用戶自定義的字體的邊界,兩者取高度差,就是用戶字體和系統自帶字體的字符高度差了。然後,再根據上文中的思路,調整對應偏移量,即可得到真正的視覺垂直居中佈局:

動態計算偏移量後實現任意字體視覺上垂直居中

 

另,有些老字體比如 宋體 就很尷尬,它在同樣大小字號下比系統默認字體的矩形還要大,但實際字體大小與系統字體相同,同時字體整體是“底部對齊”,於是差值是負數,結果導致這個字體本身就靠下了,偏移後反而更靠下了……對於這類,我大力出奇蹟,直接取絕對值就好了……🤷‍♂️

 

 

 

本文由 落格博客 原創撰寫:落格博客 » 讓 iOS macOS 中文字體實現視覺垂直居中

轉載請保留出處和原文鏈接:https://www.logcg.com/archives/3186.html

關於作者

R0uter

如非聲明,本人所著文章均為原創手打,轉載請註明本頁面鏈接和我的名字。

註釋

  1. 老哥,我也在搞垂直居中,但是沒有達到預想效果,我時使用分類重寫的edit、選擇、drawInterior和draw 方法,但是我發現edit、drawInterior和draw並沒有被調用,只有select方法在編輯狀態下會被調用,現在的結果就是,只有在編輯狀態的時候,textfield會垂直居中,退出編輯狀態後,textfield會恢復垂直居上,我該怎麼辦

發表評論

您的電子郵件地址不會被公開. 必填字段標 *