当前位置:   article > 正文

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

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

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

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

  1. let range = NSRange(location: 0, length: introduce.count)
  2. var att = NSMutableAttributedString(string: introduce)
  3. let paraStyle = NSMutableParagraphStyle()
  4. paraStyle.lineSpacing = 4
  5. att.addAttribute(.font, value: UIFont.systemFont(ofSize: 14), range: range)
  6. // 计算内容高度
  7. let screenWidth = UIScreen.main.bounds.size.width
  8. let maxSzie = CGSizeMake(screenWidth-40, CGFLOAT_MAX)
  9. // 换行模式byClipping
  10. paraStyle.lineBreakMode = .byTruncatingTail
  11. att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
  12. size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
  13. print("使用byTruncatingTail计算size ", size)

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

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

  1. func getTextAttributed(_ introduce: String) -> NSAttributedString {
  2. let range = NSRange(location: 0, length: introduce.count)
  3. var att = NSMutableAttributedString(string: introduce)
  4. let paraStyle = NSMutableParagraphStyle()
  5. paraStyle.lineSpacing = 4
  6. att.addAttribute(.font, value: UIFont.systemFont(ofSize: 14), range: range)
  7. // 计算内容高度
  8. let screenWidth = UIScreen.main.bounds.size.width
  9. let maxSzie = CGSizeMake(screenWidth-40, CGFLOAT_MAX)
  10. // 换行模式byWordWrapping
  11. paraStyle.lineBreakMode = .byWordWrapping
  12. att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
  13. var size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
  14. print("使用byWordWrapping计算size ", size)
  15. // 换行模式byCharWrapping
  16. paraStyle.lineBreakMode = .byCharWrapping
  17. att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
  18. size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
  19. print("使用byCharWrapping计算size ", size)
  20. // 换行模式byClipping
  21. paraStyle.lineBreakMode = .byClipping
  22. att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
  23. size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
  24. print("使用byClipping计算size ", size)
  25. // 换行模式byTruncatingHead
  26. paraStyle.lineBreakMode = .byTruncatingHead
  27. att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
  28. size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
  29. print("使用byTruncatingHead计算size ", size)
  30. // 换行模式byClipping
  31. paraStyle.lineBreakMode = .byTruncatingTail
  32. att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
  33. size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
  34. print("使用byTruncatingTail计算size ", size)
  35. // 换行模式byClipping
  36. paraStyle.lineBreakMode = .byTruncatingMiddle
  37. att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
  38. size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
  39. print("使用byTruncatingMiddle计算size ", size)
  40. return att
  41. }

测试后发现,系统的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. 返回富文本
  1. func getTextAttributed(_ introduce: String) -> NSAttributedString {
  2. let range = NSRange(location: 0, length: introduce.count)
  3. let att = NSMutableAttributedString(string: introduce)
  4. let paraStyle = NSMutableParagraphStyle()
  5. paraStyle.lineSpacing = 4
  6. att.addAttribute(.font, value: UIFont.systemFont(ofSize: 14), range: range)
  7. // 计算内容高度
  8. let screenWidth = UIScreen.main.bounds.size.width
  9. let maxSzie = CGSizeMake(screenWidth-40, CGFLOAT_MAX)
  10. // 换行模式byWordWrapping
  11. paraStyle.lineBreakMode = .byWordWrapping
  12. att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
  13. var size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
  14. print("使用byWordWrapping计算size ", size)
  15. // 换行模式byTruncatingTail
  16. paraStyle.lineBreakMode = .byTruncatingTail
  17. att.addAttribute(.paragraphStyle, value: paraStyle, range: range)
  18. // size = att.boundingRect(with: maxSzie, options: [.usesLineFragmentOrigin,.usesFontLeading], context: nil).size
  19. // print("使用byTruncatingTail计算size ", size)
  20. return att
  21. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/43272?site
推荐阅读
相关标签
  

闽ICP备14008679号