微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

iOS 13:如何调整UIKit / SwiftUI中自定义字体的前导/下降/行高

如何解决iOS 13:如何调整UIKit / SwiftUI中自定义字体的前导/下降/行高

我使用的是自定义字体,并且渲染可能以某种方式弄乱了行高,这可能是由于descentleading(?)配置错误造成的,因此最后切下了g和j呈现的文本行。我认为这可能是特定字体的问题,因为Sketch也暴露了所涉及字体的类似问题,但是我觉得我对印刷测量或字体的理解还不够。我发现Typographic Concepts上的Apple文档页面非常有见地。

Rendered Label exposing the cut off

我第一次使用了FontLab的测试版本来研究字体本身,这是我第一次使用-因此我几乎不知道我在看什么。 g似乎确实在配置的descent下面,这似乎是最后一行。 (?)(请参阅:Character view in FontLab,showing the descend of the g

通过linespacing,我可以调整线条本身之间的距离,以在前几行中解决此问题。我知道iOS 14将带来一种在SwiftUI中修改Text的{​​{3}}的方法。但是我需要定位到iOS 13,所以这无济于事。

我还尝试了SwiftUI的Text,普通的UILabel.textUILabel.attributedText以及自定义的段落样式,但是我在此所做的任何调整似乎都无法缓解问题。 该视图甚至没有剪切。仅向框架添加填充完全没有帮助。它增加了距离,但是g和j仍然被剪切。

我该怎么办?当最后一行中有g和j时,子类UILabel并覆盖intrinsicContentSize添加一些额外的空间?感觉a)肮脏,b)鉴于填充没有帮助,这可能无法解决问题吗?

字体本身是问题所在吗?我可以以某种方式修补字体而不会使字体更糟吗?

当我使用较低级别的API时,有什么方法可以修改字体的开头或结尾高度吗?好像我可以使用CoreText,因为CTFontCreatecopyWithAttributes(_:_:_:_:)一个候选对象,如果我可以仅通过属性修改前导,行距或下降?可以或猴子打补丁/摇动东西而不会向膝盖开枪吗?我应该只提交雷达反馈吗?

解决方法

您需要使用dotnet publish而不是String来控制UILabel的行距。这是示例代码

NSAttributedString

输出

enter image description here

,

我知道您在问什么,因为自定义字体也遇到了同样的问题。我将提供两种解决方案。在我自己的项目中,我按照您的建议进行操作,它覆盖了innerContentSize并为高度和宽度添加了一个填充乘数。就我而言,字体是面向用户的,因此我拥有一个可容纳所有相关信息的结构。 FYI Chalkduster位于系统和剪辑中。我也相信,这都是由于字体文件本身造成的。

解决方案1: 示例:

struct UserFont{
    var name : String
    var displayName : String
    var widthMultiplier : CGFloat
    var heightMultiplier : CGFloat
}   

然后在我的UILabel中将其子类化以使用这两个指标

@IBDesignable
class MultiplierUILabel: UILabel {
    @IBInspectable var widthPaddingMultiplier : CGFloat = 1
    @IBInspectable var heightPaddingMultiplier : CGFloat = 1
    override var intrinsicContentSize: CGSize{
       return CGSize(width: super.intrinsicContentSize.width * widthPaddingMultiplier,height: super.intrinsicContentSize.height * heightPaddingMultiplier)
    }
}

对我来说,这是最简单的实现,因为我相应地找到了字体和倍数比例。

解决方案2:
通过测量字形边界并调整原点y,您也许可以使绘制稍微高一些。例如,这可以修复系统中包含的Chalkduster字体的剪切。

@IBDesignable
class PaddingUILabel: UILabel {
    override func drawText(in rect:CGRect) {
        //hello
        guard let labelText = text else {  return super.drawText(in: rect) }
        //just some breathing room
        let info = boundsForAttrString(str: labelText,font: self.font!,kern: .leastNormalMagnitude)
        let glyph = info.glyph
        var newRect = rect
        let glyphPadding = -(glyph.origin.y)
        if glyphPadding - info.descent > 1 && info.descent != 0{
            newRect.origin.y -= glyphPadding/2
        }else{
            if info.descent != 0{
                newRect.origin.y += (info.descent - glyphPadding)/2
            }
        }
        super.drawText(in: newRect)
    }
    
    func boundsForAttrString(str:String,font:UIFont,kern:CGFloat)->(glyph:CGRect,descent:CGFloat){
        let attr = NSAttributedString(string: str,attributes: [.font:font,.kern:kern])
        let line = CTLineCreateWithAttributedString(attr)
        var ascent : CGFloat = 0
        var descent : CGFloat = 0
        var leading : CGFloat = 0
        
        CTLineGetTypographicBounds(line,&ascent,&descent,&leading)
        let glyph = CTLineGetBoundsWithOptions(line,.useGlyphPathBounds).integral
        return (glyph,leading != 0 ? descent : 0)
    }
}

解决方案2的结果: 系统 System

PaddingUILabel使用字形范围 PaddingUILabel

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。