IOS 6.0+ Autolayout — UITableViewCell 高度调整
要实现的效果
要求:
一般titleLabel 仅显示一行标题,高度为固定。
imageview 大小也为固定。
detailLabel 宽度固定,但高度根据文本动态调整。
cell 底部拒imageview 的底部以及detailLabel 底部高度都是大于等于20。
当detailLabel文字很少时,cell底部拒imageview底部维持20,这时detaillabel底部距cell 底部大于20.
当detailLabel文字很多时,cell底部距imageview底部超过20,与detailLabel底部高度维持20.
storyboard上的准备工作
注意将detailLabel numberOfLines 设为0
建好cell自定义AutoCell 类,关联好控件,事先准备好一些数据源
1
2
3
|
nameArray = [NSMutableArray arrayWithObjects:@ "蜗壳" ,@ "AI" ,@ "大詹皇" ,nil]; imageArray = [NSMutableArray arrayWithObjects:@ "u=4040080498,3072784853&fm=90&gp=0.jpg" ,@ "u=2384677404,2895132414&fm=21&gp=0.jpg" ,@ "u=262781505,2408318453&fm=21&gp=0.jpg" , nil]; descriptionArray = [NSMutableArray arrayWithObjects:@ "蜗壳打球好潇洒,好飘逸,铁王之王" ,@ "AI,史上最矮状元,无冕之王,crossover简直厉害,观赏性强,永远的MVP!!!!" ,@ "最年轻的一万分先生,MVP,奥布莱恩杯,效率之王,天之骄子,全宇宙最强的球员没有之一,强突暴扣身体棒,发际线又高了,关键时刻又耸了,带领骑士夺冠吧,虽然看起来还没戏!!!!!!" , nil]; |
实现tableview的委托方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
//numberOfRows -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 3; } //cellForRow -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { AutoTableViewCell *cell = (AutoTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@ "autoCell" ]; [cell.titleLabel setText:nil]; [cell.titleLabel setText:[nameArray objectAtIndex:indexPath.row]]; [cell.descriptionLabel setText:nil]; [cell.logoImageView setImage:[UIImage imageNamed:[imageArray objectAtIndex:indexPath.row]]]; [cell.descriptionLabel setText:[descriptionArray objectAtIndex:indexPath.row]]; return cell; } |
先不实现HeightForRow方法,直接运行,发现ios7,ios8上都没有得到想要的效果
IT'S SO BAD!!!
核心部分,HeightForRow方法实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { static AutoTableViewCell *cell = nil; static dispatch_once_t onceToken; //只会走一次 dispatch_once(&onceToken, ^{ cell = (AutoTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@ "autoCell" ]; }); //calculate CGFloat height = [cell calulateHeightWithtTitle:[nameArray objectAtIndex:indexPath.row] desrip:[descriptionArray objectAtIndex:indexPath.row]]; return height; } |
具体的计算高度方法是现在自定义cell类中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
-(CGFloat)calulateHeightWithtTitle:(NSString*)title desrip:(NSString*)descrip { //这里非常重要 CGFloat preMaxWaith =[UIScreen mainScreen].bounds.size.width-108; [self.detailLabel setPreferredMaxLayoutWidth:preMaxWaith]; [self.titleLabel setText:title]; //这也很重要 [self.detailLabel layoutIfNeeded]; [self.detailLabel setText:descrip]; [self.contentView layoutIfNeeded]; CGSize size = [self.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; //加1是关键 return size.height+1.0f; } |
几大需要注意的地方
首先说为什么要设置 PreferredMaxLayoutWidth, 表示label的最大的布局宽度,label显示多少行与它的宽度肯定有关,所有这里要设置正确的宽度,但这里有点坑的地方
这是storyboard 上detailLabel 的该属性,默认是没有勾选的(automatic)表示系统自动计算最大布局宽度,但是查看官方文档,你会发现自动计算只有在ios8中才会有效果,低于ios8不会自动计算。这时你可能会说:那把它勾上吧!!!
如图,勾上之后你发现显示的是492,这是什么意思?这个数字是当前使用的storyboard 的宽度减去label到两边界的绝对距离。xcode6 为大尺寸storyboard 宽度600 ,减去 detailLabel 距左边界98,减去距右边界10,刚好492.
但是这样对吗?很明显不对,iphone 屏幕宽度不是已经有3种宽度了么?320、375(iphone6)、414(plus)
所以600很明显不对,应该用当前运行的宽度来减去108,所以这里勾不勾都是错,干脆不勾了直接代码算吧....
1
|
CGFloat preMaxWaith =[UIScreen mainScreen].bounds.size.width-108; |
关于layoutIfNeeded到底是干嘛的,我也是一知半解,只知道不加效果出不来,打算之后再去查阅...
加1是关键
1
2
|
[self.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; return size.height+1.0f; |
这里size.height 实际上是我们要的contentview 的高度,但是我们如果直接将这个高度返回,就赋给了cell的高度,但是由于cell 分界线的原因,cell的高度比contentview高度多1,所以这里加1再返回。不要小看1像素,少了它效果还真就出不来!!!!
注意了这些,我们再运行,发现得到了想要的效果,切换模拟器,也没问题。
在ios6.0上测试
没有6.0的模拟器了,找了台6.0的真机,测试后效果如图
detailLabel的高度始终没有改变,维持在一行,但是可以发现cell的高度是对的,这似乎说明heightforrow方法没问题,那detailLabel为何没有自动拉伸呢?
再次检查了代码,原来问题出在cellforrow方法中,因为每个cell上的detailLabel的高度要拉伸就应该给每个
detailLabel设置最大布局宽度:preferredMaxLayoutWidth。之前做的仅仅只是在heightforrow里面的得到那个
用来计算的cell设置过。所以加了几句代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { AutoTableViewCell *cell = (AutoTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@ "autoCell" ]; [cell.titleLabel setText:nil]; [cell.titleLabel setText:[nameArray objectAtIndex:indexPath.row]]; //补上的几句,给用来显示的DetailLabel 设置最大布局宽度 CGFloat preMaxWaith =[UIScreen mainScreen].bounds.size.width-108; [cell.detailLabel setPreferredMaxLayoutWidth:preMaxWaith]; [cell.detailLabel layoutIfNeeded]; [cell.detailLabel setText:nil]; [cell.logoImageView setImage:[UIImage imageNamed:[imageArray objectAtIndex:indexPath.row]]]; [cell.detailLabel setText:[descriptionArray objectAtIndex:indexPath.row]]; return cell; } |
再次运行,可以看到在ios6中也得到了想要的效果,
IT'S perfect!!!
总之,研究了几天布局,发现ios好坑,各种陷阱,好在查阅了中外各种资料,最终还是实现了效果。
IOS 6.0+ Autolayout — UITableViewCell 高度调整的更多相关文章
- iOS7.0中UILabel高度调整注意事项(转)
注释:原文链接丢失. 我的“记词助手”在升级到iOS7之后,一直出现UILabel错位的问题: 我的label是用- (CGSize)sizeWithFont:(UIFont *)font const ...
- iOS7.0中UILabel高度调整注意事项
转自:http://blog.csdn.net/k12104/article/details/33731833 http://herkuang.info/blog/2013/12/31/ios7%E4 ...
- UITableViewCell高度自适应的关键点
iOS开发中对于UITableViewCell高度自适应的文章已经很多很多,但如果cell内容比较复杂,刚使用autolayout配置自使用时还是总不能一次性成功. KEY POINT 这里只说设置的 ...
- 动态调整UITableViewCell高度的实现方法
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPa ...
- UITableViewCell高度自适应探索--AutoLayout结合Frame
UITableViewCell高度自适应探索--UITableView+FDTemplateLayoutCell地址: http://www.jianshu.com/p/7839e3a273a6UIT ...
- 优化UITableViewCell高度计算的那些事
优化UITableViewCell高度计算的那些事 我是前言 这篇文章是我和我们团队最近对 UITableViewCell 利用 AutoLayout 自动高度计算和 UITableView 滑动优化 ...
- 优化UITableViewCell高度计算的那些事(RunLoop)
这篇总结你可以读到: UITableView高度计算和估算的机制 不同iOS系统在高度计算上的差异 iOS8 self-sizing cell UITableView+FDTemplateLayout ...
- UITableViewCell 高度计算从混沌初始到天地交泰
[原创]UITableViewCell 高度计算从混沌初始到天地交泰 本文主要基予iOS UITableViewCell 高度自适应计算问题展开陈述,废话少说直入正题: UITableView控件可能 ...
- 《转》优化UITableViewCell高度计算的那些事
我是前言 这篇文章是我和我们团队最近对 UITableViewCell 利用 AutoLayout 自动高度计算和 UITableView 滑动优化的一个总结.我们也在维护一个开源的扩展,UITabl ...
随机推荐
- C# winCE5.0开发右键效果解决方案
用VS2008开发C#语言wince程序,发现程序里右键捕获不到,采集器上点也没反应,上网查好像有个c++版本的,看不懂啊,下面我给出C#实现右键效果的解决方案,请各位多多优化. 首先控件Contex ...
- css3选择符使用个人理解。
元素选择符: 通配选择符:一般用* 星号表示 他会命中整体标签. 类型选择符:一般用者空格表示 他会命中标签自己的所有子元素. ID选择符: 一般用# 井号表示 他会命中以id为属性的标签 ...
- 通过Url传多个参数方法
MVC3通过URL传值,一般情况下都会遇到[从客户端(&)中检测到有潜在危险的 Request.Path 值]的问题 这个问题的解决方法,我的其他博文已经有了说明,这里给出连接[从客户端(&a ...
- tomcat启动报错总结
错误一 webapps\ROOT does not exist or is not a readable directory 错误原因:在tomcat的server.xml的context中配置了不存 ...
- C# 汉子增加UTF-8头
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Conv ...
- MediaWiki基本设置
1.左侧导航栏设置 在右上角搜索栏中输入“mediawiki:sidebar” 确认后进行编辑(需要以站长或管理员身份登录). 格式: *导航栏名称一 **链接一地址|链接一名称 **链接二地址|链接 ...
- 初学mysql命令
创建数据库mydb: create database mydb; 运行sql脚本文件:(连接数据库后) \. e:\myphpWeb\createTables.sql 删除数据库mydb: drop ...
- Javascript计算密码的强度
用Javascript评估用户输入密码的强度 1.如果密码少于5位,那么就认为这是一个弱密码.2.如果密码只由数字.小写字母.大写字母或其它特殊符号当中的一种组成,则认为这是一个弱密码.3.如果密码由 ...
- dedecms文章的更新时间问题 每次更改文章时间变成最新的
dedecms 每次更改文章,更新时间这里每次改了后再来看又变成当前最新时间的了. 解决方法: 查找后台目录的 templets/article_edit.htm 这个文件. 然后打开,查找如下代码: ...
- Repeater绑定数据库,使用AspNetPager进行分页
分页是Web中经常遇到的功能,分页主要有真分页和假分页. 所谓真分页是指:每一页显示多少数据,就从数据库读多少数据: 假分页是指:一次性从数据库读取所有数据,然后再进行分页. 这两种分页方式区别在于从 ...