前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Cell 动态行高文字显示不全问题探索

Cell 动态行高文字显示不全问题探索

作者头像
woopDast1
发布2021-02-25 16:20:59
1.9K0
发布2021-02-25 16:20:59
举报
文章被收录于专栏:iOSeriOSer

问题概述

使用的是”预估行高+自动布局“的方法实现动态行高(适用于 iOS7.0 以后系统)。

预估行高:

代码语言:javascript
复制
self.gTV.estimatedRowHeight = 90;
self.gTV.rowHeight = UITableViewAutomaticDimension;

自动布局,又叫 autolayout,为了使文本可以多行显示,需要保证如下设置:

  • 设置 label 的 numberoflines 为 0
  • 对 label 进行上左下右的完整约束

在项目实现过程中,遇到了文本内容被截断最后一行一小部分,无法完全显示的问题。

为了复现项目中遇到的此问题并找到原因,做了如下尝试:

一、新建工程

新建工程测试,cell上下约束完备,底部高度约束 contentLblBtmCon 为>=9,优先级默认1000。发现预估行高是正常的。

效果如下:

Simulator Screen Shot - iPhone SE (1st generation) - 2021-02-07 at 15.27.32
Simulator Screen Shot - iPhone SE (1st generation) - 2021-02-07 at 15.27.32

二、尝试复现问题

隐藏系统cell分割线:self.gTV.separatorStyle = UITableViewCellSeparatorStyleNone;

同时,在自定义cell中重写 setFrame方法实现分割线效果,结果发现文字开始显示不全了!

代码语言:javascript
复制
- (void)setFrame:(CGRect)frame{
    frame.size.height -= 8;
    [super setFrame:frame];
}

约束报错如下:

代码语言:javascript
复制
2021-02-07 14:56:37.416314+0800 DynamicCellHeightTest[60202:8764494] [LayoutConstraints] Unable to simultaneously satisfy constraints.
	Probably at least one of the constraints in the following list is one you don't want. 
	Try this: 
		(1) look at each constraint and try to figure out which you don't expect; 
		(2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x6000033a5810 UILabel:0x7f898d0072c0.height == 21   (active)>",
    "<NSLayoutConstraint:0x6000033a59f0 UILabel:0x7f898d016da0.height >= 20.5   (active)>",
    "<NSLayoutConstraint:0x6000033df2a0 V:|-(16)-[UILabel:0x7f898d0072c0]   (active, names: '|':UITableViewCellContentView:0x7f898d0061f0 )>",
    "<NSLayoutConstraint:0x6000033df340 V:[UILabel:0x7f898d0072c0]-(NSSpace(8))-[UILabel:0x7f898d016da0]   (active)>",
    "<NSLayoutConstraint:0x6000033df430 V:[UILabel:0x7f898d016da0]-(>=9)-|   (active, names: '|':UITableViewCellContentView:0x7f898d0061f0 )>",
    "<NSLayoutConstraint:0x6000033ddb80 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7f898d0061f0.height == 86   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x6000033a59f0 UILabel:0x7f898d016da0.height >= 20.5   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.

通过 log 可知,内容 label 的高度约束被舍弃了,因此会出现内容显示不全的问题。模拟器运行效果:

Simulator Screen Shot - iPhone SE (1st generation) - 2021-02-07 at 15.28.30
Simulator Screen Shot - iPhone SE (1st generation) - 2021-02-07 at 15.28.30

尝试解决

修改contentLblBtmCon优先级为High(750)

截屏2021-02-07 下午3.14.06
截屏2021-02-07 下午3.14.06

结果还是不太行:

Simulator Screen Shot - iPhone SE (1st generation) - 2021-02-07 at 15.29.15
Simulator Screen Shot - iPhone SE (1st generation) - 2021-02-07 at 15.29.15

修改contentLblBtmCon优先级为Low(250)

截屏2021-02-07 下午3.18.00
截屏2021-02-07 下午3.18.00

效果如下:

Simulator Screen Shot - iPhone SE (1st generation) - 2021-02-07 at 15.26.05
Simulator Screen Shot - iPhone SE (1st generation) - 2021-02-07 at 15.26.05

可见,此时内容可以显示全了,Xcode 也不报错了。但是内容距离 cell 底部的距离太小了,并没有大于 9。猜测:这个底部约束因为优先级是Low,所以被系统舍弃,使得内容可以显示完整,同时导致内容距离 cell 底部的距离太小。

但是,当我尝试设置底部约束的为 >= 9+8=17,再运行,居然就是我想要的效果:

Simulator Screen Shot - iPhone SE (1st generation) - 2021-02-07 at 15.40.45
Simulator Screen Shot - iPhone SE (1st generation) - 2021-02-07 at 15.40.45
Simulator Screen Shot - iPhone SE (1st generation) - 2021-02-07 at 15.40.53
Simulator Screen Shot - iPhone SE (1st generation) - 2021-02-07 at 15.40.53

分析:系统先在 setFrame 生效之前,对 cell 内的上下所有约束进行行高预估。计算拿出结果后缓存。在 cell 显示之前,setFrame 生效,此时,cell 在之前预估行高的基础上,根据约束重新布局,舍弃了内容 label 的高度约束,导致内容显示不全。

当我们把底部约束的优先级降低到 Low 时,cell 在之前预估行高的基础上,根据约束重新布局,舍弃的就是低优先级的底部约束了,因此才能看到低优先级底部约束开始生效,后来因 setFrame 减小了高度,导致底部间隔变小的效果。此时,我们将计就计,把底部约束增加 cell 间隔高度(8),即可得出我们想要的效果!

小结

重写 cell 的 setFrame 方法改变 cell 高度来实现分割线效果时,可能导致多行 label 显示不全,此时,可以通过降低底部约束优先级为 Low + 增加底部约束的值(cell 间距),来实现想要的文本多行显示效果。

其他解决思路

当然,为了实现行分割线效果,我们也可以在自定义 cell 的底部手动添加一个 UIView 子视图,高度设置为 cell 间隔高度,颜色改为与 UITableview 背景色一致(与 cell 背景色不同),也能达到同样的效果。这种方法就不会因为重写 cell 的 setFrame 方法导致多行文字显示不全了。但是,当 cell 有选中效果或左滑删除效果时,相关效果就不是很好了,因为分隔线 View 属于 cell 的一部分被一起选中或移动,看起来效果有点不太好。

好了,这次的探索就到这里了。下面附上测试用的源代码,欢迎 star!3Q!

源代码地址

OCDailyTests/DynamicCellHeightTest

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-02-07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题概述
  • 一、新建工程
  • 二、尝试复现问题
  • 尝试解决
    • 修改contentLblBtmCon优先级为High(750)
      • 修改contentLblBtmCon优先级为Low(250)
      • 小结
      • 其他解决思路
      • 源代码地址
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档