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

news2024/11/16 15:30:20

在一次开发过程中,发现带有行间距的富文本计算高度,会有不准确的情况,富文本内容明明很长,但是计算出的高度只有不到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
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1430367.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Simulink系列】——动态系统仿真 之 简单系统

引入 不同的系统具有不同的输入与输出。一般来说,输入输出数目越多,系统越复杂。最简单的系统只要一个输入一个输出(SISO),且其任意时刻的输出只与当前时刻的输入有关。 一、简单系统定义 对于满足下列条件的系统&a…

android 网络拦截器统一处理请求参数和返回值加解密实现

前言 项目中遇到参数加密和返回结果加密的业务 这里写一下实现 一来加深记忆 二来为以后参考铺垫 需求 项目在开发中涉及到 登陆 发验证码 认证 等前期准备接口 这些接口需要单独处理 比如不加密 或者有其他的业务需求 剩下的是登陆成功以后的业务需求接口 针对入参和返回值…

【Android新版本兼容】onBackPressed()方法被弃用的解决方案

提示:此文章仅作为本人记录日常学习使用,若有存在错误或者不严谨得地方欢迎指正。 文章目录 一、使用 AndroidX API 实现预测性返回手势1.1 添加依赖1.2 启用返回手势1.3 注册OnBackPressedCallback()方法来处理返回手势 一、使用 AndroidX API 实现预测…

【MIT 6.S081】2020, 实验记录(5),Lab: lazy allocation

目录 Task 1: Eliminate allocation from sbrk()Task 2: Lazy allocationTask 3: Lazytests and Usertests 在学习了 page fault 这一节课后,了解了操作系统是如何结合 page table 和 trap 利用 page fault 来实现一系列的神奇的功能。这个 lab 就是在 XV6 中实现 l…

前端面试拼图-数据结构与算法

摘要:总结一些前端算法题,持续更新! 一、数据结构与算法 时间复杂度-程序执行时需要的计算量(CPU) 空间复杂度-程序执行时需要的内存空间 前端开发:重时间,轻空间 1.把一个数组旋转k步 arr…

CSS的复合选择器

一,什么是复合选择器 常用的复合选择器有:后代选择器、子选择器、并集选择器和伪类选择器。 二,后代选择器(用空格)(重点) 后代选择器也称包含选择器,可以选择父元素里面的子元素。写法就是外层标签在前面,内层标签写后面,中间要有空格隔开。当标签发生嵌套时,内层…

PostgreSQL 也很强大,为何在中国大陆,MySQL 成为主流,PostgreSQL 屈居二线呢?

问题: PostgreSQL 也很强大,为何在中国大陆,MySQL 成为主流,PostgreSQL 屈居二线呢?PostgreSQL 能否替代 MySQL? 当我们讨论为何 MySQL 在中国大陆成为主流而 PostgreSQL 屈居二线时, 我们其实…

servlet会话API

servlet会话API 您可以使用servlet会话API中定义的类和接口来创建和管理用户会话。servlet会话API提供的用于创建和管理用户会话的各种接口有javax.servlet.http.HttpSession、javax.servlet.httpSessionListener和javax.servlet.http.HttpSessionBindingListener和javax.serv…

unity角色触摸转向

1、挂载脚本到角色的父物体A上 2 、以屏幕左边的触摸为移动,右边为转向操作 3、加载角色时,将角色的父物体设置为A,须将角色的位置和角度置0 using System; using System.Collections; using System.Collections.Generic; using UnityEngin…

OTG -- STM32 OTG驱动代码下载及简述(三)

目录 前沿 1 STM32 OTG标准库的获取 2 设备模式代码匹配开发板 2.1 OTG FS全速代码修改 2.2 OTG HS代码修改 2.2.1 OTG HS外部高速PHY运行在高速模式代码修改 2.2.2 OTG HS外部高速PHY运行在全速模式代码修改 2.2.3 OTG HS内部全速PHY运行在全速模式代码修改 前沿 前面…

linux 组建和卸载raid1、raid0详细操作

组raid的最好是相同容量和型号的硬盘,否则会有木桶效应 linux下组raid有很多细节 一、安装raid软件 deb包 apt-get install mdadm或dnf包 dnf install mdadm二、组raid1-镜像,组raid0-并列 raid1和raid0只有在madam命令时一点点不同,其他…

python 下载腾讯在线文档

import requests""" 1. 手动到chrome获取下载请求 2. 获取excel的动态id 3. 拼出excel的下载链接 4. 下载 """class Excel:def __init__(self):self.cookie_string ""self.headers {"authority": "docs.qq.com"…

中缀转后缀

概念 什么是后缀表达式? 后缀表达式,其实就是一个中缀表达式 AOB > ABO (A、B是式子、O 为运算符),将运算符向后放 中转后举例 中缀表达式:(a b)* c - (d / c) 首先&#xff…

CANoe学习笔记—关于cfg工程界面的分类

创建一个工程过程中,如何规划好界面设置,对于后续使用和维护起到了非常好的作用。故整理下 1:首先规划好大致结构图 CANoe中工程的规划Trace界面ConfigurationBuildInToolControlDiagnosticPanel预留 当然:此格式不是固定的&…

高级FPGA开发之基础协议PCIe

基础协议之PCIe部分 一、TLP包的包头 在PCIe的系统中,tlp包的包头的结构有许多部分是相似的,通过掌握这些常规的包头,能帮助理解在PCIe总线上各个设备之间如何进行数据的收发。 通用的字段 通用字段作用Fmt决定了包头是3DW还是3DW&#xff…

20240203在WIN10下配置stable-diffusion-webui.git

20240203在WIN10下配置stable-diffusion-webui.git 2024/2/3 11:55 【结论:在WIN10下,生成512x512分辨率的图像,大概需要9秒钟!】 【结论:在Ubuntu20.04.6下,生成512x512分辨率的图像,大概需要1…

Unity 图片不改变比例适配屏幕

Unity 图片不改变比例适配屏幕 前言项目场景布置代码编写添加并设置脚本效果 前言 遇到一个要让图片适应相机大小,填满屏幕,但不改变图片比例的需求,记录一下。 项目 场景布置 代码编写 创建AdaptiveImageBackground脚本 using System.C…

Unity项目从built-in升级到URP(包含早期版本和2023版本)

unity不同版本的升级URP的方式不一样,但是大体流程是相似的 首先是加载URP包 Windows -> package manager,在unity registry中找到Universal RP 2023版本: 更早的版本: 创建URP资源和渲染器​​ 有些版本在加载时会自动创建&#…

【全网独创】2024美赛E题33页成品论文+1-4问完整代码数据助攻

E题社区抗灾能力综合评估与决策模型研究 摘要:社区抗灾能力的提升对于灾害风险管理至关重要。本研究基于机器学 习方法,构建了社区抗灾能力预测模型,以评估社区在灾害事件中的表现。首先, 我们采用梯度提升树模型对社区基础设施、…

Node.js 模块化

一、介绍 1.1 什么是模块化与模块 ? 将一个复杂的程序文件依据一定规则(规范)拆分成多个文件的过程称之为 模块化 其中拆分出的 每个文件就是一个模块 ,模块的内部数据是私有的,不过模块可以暴露内部数据以便其他 模块使用 1…