NSTextField 文本模糊的解決辦法 canDrawSubviewsIntoLayer

在開發落格輸入法 macOS 的過程當中,我一直被一個奇怪的問題所困擾——文本模糊。

次像素

無論我怎樣調試,落格輸入法的候選文字都無法達到原生文字的那樣清晰和銳利。在請教了大神之後,得到的活久見經驗是——上游次像素渲染 錯誤。

在很多平台都有類似問題,macOS 底層渲染也有這樣的錯誤,一旦你的佈局出現了小數點或者不是整數,就會導致文本渲染模糊。

那么怎么解决呢?只要把位置和大小“对正”就可以了不要直接使用 Int(XXX) 来转换你的数值,使用 roundf() ,不過,对于 Swift 来说我们有更方便的方式,比如這樣:

rounded() 方法就是我们常说的“四舍五入”如果你直接转换数据类型到整形那么小数点后的内容会被直接抛弃哪怕是 0.99999也会变成 0显然这并不是我们想要的如果用这个函数来转换那么你得到的还是 CGFloat但值却变成了原本的四舍五入“整数”

确实好了很多不会那么模糊了但如果你仔细看总感觉还是有哪里不太一样

實際上,这个 bug 在最新的 macOS 10.14 Mojave 中已经修复了

canDrawSubviewsIntoLayer

还有的人说是因为你用了 layer这样就会导致性能底下如果把 wantsLayer 關閉,或者给一个非透明的背景就会好很多但这终究不是个办法如果必须要透明呢?总之我经过查询找到了这个方法 canDrawSubviewsIntoLayer

苹果官方的文档对它是这么描述的

当这个属性的值是 true任何任何子视图隐式创建的 layer——也就是说那些你没有通过设置 wantsLayer 屬性為 true 创建的 layer都会把自己绘制在当前视图的 layer上换句话说就是子视图不再拥有自己的layer相反他们把自身的内容绘制在父视图的 layer中所有受影响的视图都使用 draw(_:) 方法来绘制内容它们不再使用 updateLayer() 方法更新 layer 内容就算 wantsUpdateLayer 属性设置为 true

使用这个属性来为基于 layer 的视图和子视图扁平化 layer 继承扁平化 layer 集成减少了你试图继承中的 layer 数量(并且还可能减少内存的使用)减少 layer 数量可以在大量视图和子视图内容不明显变化的情况下更加高效。比如說,扁平化继承降低了组合视图时使用的时间不要扁平化视图继承如果你准备给子视图添加动画的话

当改变这个属性的值时当前视图必须拥有一个 layer 对象该属性默认值为

我把英文翻译过来了,實際上,就可以理解为是 Photoshop 里的“合并图层”如果你的视图组合不做大的改变那么就可以把它们合并绘制不需要去管什么透明度和渐变了直接把最终的效果绘制在同一个图层上大大降低了渲染成本这样文本也就不再模糊变得清晰锐利

由...出版 R0uter

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

發表評論

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