You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS脚本类字体文本尺寸计算异常,如何获取正确宽度?

解决UITextView脚本类字体文本尺寸计算不准确的问题

脚本类字体(如Radicalis、Allura)的字形常存在超出标准排版边界的部分,UITextView自带的sizeThatFits(_:)方法仅基于文本的排版基线计算尺寸,无法覆盖这类特殊字形的视觉范围,导致字母被截断。以下是几种可靠的解决方式:

1. 用CoreText计算精确视觉尺寸

CoreText会完整考虑字形的所有视觉元素,包括超出基线的部分,能返回最准确的文本尺寸。实现代码如下:

func getExactTextSize(text: String, font: UIFont, maxWidth: CGFloat = .greatestFiniteMagnitude) -> CGSize {
    let attrString = NSAttributedString(string: text, attributes: [.font: font])
    let frameSetter = CTFramesetterCreateWithAttributedString(attrString as CFAttributedString)
    
    // 获取约束下的建议尺寸
    let suggestedSize = CTFramesetterSuggestFrameSizeWithConstraints(
        frameSetter,
        CFRange(location: 0, length: attrString.length),
        nil,
        CGSize(width: maxWidth, height: .greatestFiniteMagnitude),
        nil
    )
    
    // 向上取整避免小数尺寸导致的截断
    return CGSize(width: ceil(suggestedSize.width), height: ceil(suggestedSize.height))
}

使用时直接用这个方法获取尺寸,再设置UITextView的frame即可。

2. 调整UITextView的容器内边距

如果不想引入CoreText,可通过调整textContainerInset和lineFragmentPadding给特殊字体预留额外空间:

// 给上下边距增加预留空间,数值可根据字体调整
textView.textContainerInset = UIEdgeInsets(top: 6, left: 0, bottom: 6, right: 0)
// 移除左右默认内边距,避免额外宽度占用
textView.textContainer.lineFragmentPadding = 0

这种方式属于临时补救,不同字体需要调整不同的内边距数值,通用性较弱。

3. 结合两种方式优化

先通过CoreText获取精确尺寸,再给UITextView设置frame时,额外增加少量内边距作为缓冲,确保极端情况下内容也不会被截断:

let exactSize = getExactTextSize(text: yourText, font: selectedFont)
textView.frame = CGRect(x: textView.frame.origin.x, y: textView.frame.origin.y, width: exactSize.width, height: exactSize.height)
textView.textContainerInset = UIEdgeInsets(top: 2, left: 0, bottom: 2, right: 0)

内容的提问来源于stack exchange,提问作者Dipesh Patel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 06:52:33