要实现的效果

要求:

一般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好坑,各种陷阱,好在查阅了中外各种资料,最终还是实现了效果。

项目源码:https://github.com/zhangxh6931/AutolayoutCell

IOS 6.0+ Autolayout — UITableViewCell 高度调整的更多相关文章

  1. iOS7.0中UILabel高度调整注意事项(转)

    注释:原文链接丢失. 我的“记词助手”在升级到iOS7之后,一直出现UILabel错位的问题: 我的label是用- (CGSize)sizeWithFont:(UIFont *)font const ...

  2. iOS7.0中UILabel高度调整注意事项

    转自:http://blog.csdn.net/k12104/article/details/33731833 http://herkuang.info/blog/2013/12/31/ios7%E4 ...

  3. UITableViewCell高度自适应的关键点

    iOS开发中对于UITableViewCell高度自适应的文章已经很多很多,但如果cell内容比较复杂,刚使用autolayout配置自使用时还是总不能一次性成功. KEY POINT 这里只说设置的 ...

  4. 动态调整UITableViewCell高度的实现方法

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPa ...

  5. UITableViewCell高度自适应探索--AutoLayout结合Frame

    UITableViewCell高度自适应探索--UITableView+FDTemplateLayoutCell地址: http://www.jianshu.com/p/7839e3a273a6UIT ...

  6. 优化UITableViewCell高度计算的那些事

    优化UITableViewCell高度计算的那些事 我是前言 这篇文章是我和我们团队最近对 UITableViewCell 利用 AutoLayout 自动高度计算和 UITableView 滑动优化 ...

  7. 优化UITableViewCell高度计算的那些事(RunLoop)

    这篇总结你可以读到: UITableView高度计算和估算的机制 不同iOS系统在高度计算上的差异 iOS8 self-sizing cell UITableView+FDTemplateLayout ...

  8. UITableViewCell 高度计算从混沌初始到天地交泰

    [原创]UITableViewCell 高度计算从混沌初始到天地交泰 本文主要基予iOS UITableViewCell 高度自适应计算问题展开陈述,废话少说直入正题: UITableView控件可能 ...

  9. 《转》优化UITableViewCell高度计算的那些事

    我是前言 这篇文章是我和我们团队最近对 UITableViewCell 利用 AutoLayout 自动高度计算和 UITableView 滑动优化的一个总结.我们也在维护一个开源的扩展,UITabl ...

随机推荐

  1. USB设备架构

    USB设备,分为3层:1.底层为传送和接受数据的总线接口:2.中间层处理总线和不同端点的数据传输:3.最高层由串行总线设备提供.主要研究中间层. USB设备状态,主要研究外部可见状态. 1,连接态-- ...

  2. Android推送等耗电原因剖析

    原文链接:http://www.jianshu.com/p/584707554ed7 Android手机有两个处理器,一个是Application Processor(AP)基于ARM处理器,主要运行 ...

  3. 导入表数据 txt

    导入表数据 txt mysql> load data infile "D:/import.txt" into table shop;输出: Query OK, rows af ...

  4. 对于js原型和原型链继承的简单理解(第三种,复制继承)

    复制继承:简单理解,就是把父对象上的所有属性复制到自身对象上: function Cat(){ this.climb = function(){ alert("我会爬树"); } ...

  5. canvas制作简单动画

    在画布元素<canvas>中,除了绘制图形.图像.文字外,还可以制作一些简单的动画,制作过程十分简单,主要分为两步操作: 1.自定义一个函数,用于图形的移动或其他动作. 2.使用setIn ...

  6. 关于本地$.get(url,function(data)),异步获取数据

    起初 此处url为本地同目录下的html片段 $.get(url,function(data) { alert(url); $("#gallery").append(data); ...

  7. JS原型的剖析与理解

    原型相关的概念 关于面向对象的概念 类 class 在js中就是构造函数 在传统的面向对象语言中,使用一个叫类的东西定义模版,然后使用模版创建对象 在构造方法中也具有类似的功能,因此称其为类 实例与对 ...

  8. 棋盘上的距离 - Grids1657

    棋盘上的距离 问题描述: 写一个程序,给定起始位置和目标位置,计算王.后.车.象从起始位置走到目标位置所需的最少步数. 王:横.直.斜都可以走,但每步限走一格. 后:横.直.斜都可以走,每步格数不受限 ...

  9. uC/OS-II内核架构解析(2)---uC/OS-II基本介绍(转)

    1. uC/OS-II文件结构 2. uC/OS-II组成部分 uC/OS-II大致可以分成系统核心(包含任务调度).任务管理.时间管理.多任务同步与通信.内存管理.CPU移植等部分. (1) 核心部 ...

  10. BASE64的实现

    原由 项目中经常需要使用base64进行处理,通过base64可以将特殊字符转化为普通可见字符,便于网络传输,代价是增长了传输长度. base64将每3个byte转化为4个6bit位,然后高位补两个零 ...