iOS 包含行间距计算富文本size

在一次开发过程中,发现带有行间距的富文本计算高度,会有不准确的情况,富文本内容明明很长,但是计算出的高度只有不到20像素,导致整个cell的高度计算异常。

需求上是文字固定宽度,最多显示3行,超过3行尾部打点展示。按照需求设置了尾部打点 paraStyle.lineBreakMode = .byTruncatingTail, 然后计算富文本的大小。

let range = NSRange(location: 0, length: introduce.count)
var att = NSMutableAttributedString(string: introduce)
let paraStyle = NSMutableParagraphStyle()
paraStyle.lineSpacing = 4
att.addAttribute(.font, value: UIFont.systemFont(ofSize: 14), range: range)
// 计算内容高度
let screenWidth = UIScreen.main.bounds.size.width
let maxSzie = CGSizeMake(screenWidth-40, CGFLOAT_MAX)

// 换行模式byClipping
paraStyle.lineBreakMode = .byTruncatingTail
att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
print("使用byTruncatingTail计算size ", size)

这时候算出来的size高度只有17像素,真实显示到屏幕上Label的高度是58像素。导致整体cell的高度计算错误。

后来发现先将换行模式改为paraStyle.lineBreakMode = .byWordWrapping 在计算高度是正确的。于是把所有的换行模式都逐个测试,看看到底是什么情况。


func getTextAttributed(_ introduce: String) -> NSAttributedString {

    let range = NSRange(location: 0, length: introduce.count)
    var att = NSMutableAttributedString(string: introduce)
    let paraStyle = NSMutableParagraphStyle()
    paraStyle.lineSpacing = 4
    att.addAttribute(.font, value: UIFont.systemFont(ofSize: 14), range: range)
    // 计算内容高度
    let screenWidth = UIScreen.main.bounds.size.width
    let maxSzie = CGSizeMake(screenWidth-40, CGFLOAT_MAX)


    // 换行模式byWordWrapping
    paraStyle.lineBreakMode = .byWordWrapping
    att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
    var size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
    print("使用byWordWrapping计算size ", size)


    // 换行模式byCharWrapping
    paraStyle.lineBreakMode = .byCharWrapping
    att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
    size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
    print("使用byCharWrapping计算size ", size)

    // 换行模式byClipping
    paraStyle.lineBreakMode = .byClipping
    att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
    size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
    print("使用byClipping计算size ", size)


    // 换行模式byTruncatingHead
    paraStyle.lineBreakMode = .byTruncatingHead
    att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
    size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
    print("使用byTruncatingHead计算size ", size)


    // 换行模式byClipping
    paraStyle.lineBreakMode = .byTruncatingTail
    att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
    size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
    print("使用byTruncatingTail计算size ", size)


    // 换行模式byClipping
    paraStyle.lineBreakMode = .byTruncatingMiddle
    att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
    size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
    print("使用byTruncatingMiddle计算size ", size)

    return att
}

测试后发现,系统的5个枚举中,只有 byWordWrapping和byCharWrapping 计算准确,带有截断方式的case,计算都是错误的。

  • case byWordWrapping = 0 // Wrap at word boundaries, default
  • case byCharWrapping = 1 // Wrap at character boundaries
  • case byClipping = 2 // Simply clip
  • case byTruncatingHead = 3 // Truncate at head of line: "...wxyz"
  • case byTruncatingTail = 4 // Truncate at tail of line: "abcd..."
  • case byTruncatingMiddle = 5 // Truncate middle of line:  "ab...yz"

好吧,系统这个样子,我们也没有办法,最后采用的方式

  1. 先用 byWordWrapping 计算高度
  2.  高度计算完成,在修改换行模式,paraStyle.lineBreakMode = .byTruncatingTail 
  3. 返回富文本
func getTextAttributed(_ introduce: String) -> NSAttributedString {

    let range = NSRange(location: 0, length: introduce.count)
    let att = NSMutableAttributedString(string: introduce)
    let paraStyle = NSMutableParagraphStyle()
    paraStyle.lineSpacing = 4
    att.addAttribute(.font, value: UIFont.systemFont(ofSize: 14), range: range)
    // 计算内容高度
    let screenWidth = UIScreen.main.bounds.size.width
    let maxSzie = CGSizeMake(screenWidth-40, CGFLOAT_MAX)

    // 换行模式byWordWrapping
    paraStyle.lineBreakMode = .byWordWrapping
    att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
    var size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
    print("使用byWordWrapping计算size ", size)

    // 换行模式byTruncatingTail
    paraStyle.lineBreakMode = .byTruncatingTail
    att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
    // size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
    // print("使用byTruncatingTail计算size ", size)

    return att
}

相关推荐

  1. IOS 计算文本的高度方法

    2024-01-28 09:42:02       59 阅读
  2. 【Electron】文本编辑器之回车换

    2024-01-28 09:42:02       52 阅读
  3. excel 如何自动调整间距 vba

    2024-01-28 09:42:02       41 阅读
  4. linux Shell 命令-08-file include 文件包含

    2024-01-28 09:42:02       45 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-28 09:42:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-28 09:42:02       101 阅读
  3. 在Django里面运行非项目文件

    2024-01-28 09:42:02       82 阅读
  4. Python语言-面向对象

    2024-01-28 09:42:02       91 阅读

热门阅读

  1. BloonsTD6 游戏拆解

    2024-01-28 09:42:02       45 阅读
  2. Web 安全之点击劫持(Clickjacking)攻击详解

    2024-01-28 09:42:02       51 阅读
  3. php函数 二

    2024-01-28 09:42:02       38 阅读
  4. 在React中使用React.createRef:更优雅的DOM引用方式

    2024-01-28 09:42:02       56 阅读
  5. ubuntu和树莓派下vim插件管理

    2024-01-28 09:42:02       54 阅读
  6. MySQL SQL 注入

    2024-01-28 09:42:02       60 阅读
  7. vue父子组件传值问题

    2024-01-28 09:42:02       39 阅读
  8. Go MongoDB Driver 中的 A D M E 类型是什么

    2024-01-28 09:42:02       48 阅读
  9. 8-Docker网络命令之prune

    2024-01-28 09:42:02       51 阅读
  10. DAY31:贪心算法入门455、53、376

    2024-01-28 09:42:02       61 阅读
  11. MySQL中一条更新语句是怎么执行的?

    2024-01-28 09:42:02       60 阅读