动态计算UITableViewCell高度

UILabel in UITableViewCell

Auto Layout - UILabel的属性Lines设为了0表示显示多行。Auto Layout约束一定要建立完完整 - UITableView使用C1.xib中自定义的Cell,那么我们需要向UITableView进行注册

 UINib *cellNib = [UINib nibWithNibName:@"C1" bundle:nil];
[self.tableView registerNib:cellNib forCellReuseIdentifier:@"C1"];
  • 数据源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return self.tableData.count; }
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
C1 *cell = [self.tableView dequeueReusableCellWithIdentifier:@"C1"];
cell.t.text = [self.tableData objectAtIndex:indexPath.row]; return cell;
}
  • 需要用到一个新的API systemLayoutSizeFittingSize:来计算UITableViewCell所占空间高度。Cell的高度是在- (CGFloat)tableView:(UITableView )tableView heightForRowAtIndexPath:(NSIndexPath )indexPath这个UITableViewDelegate的方法里面传给UITableView的。
  • 这里有一个需要特别注意的问题,也就是效率问题。UITableView是一次性计算完所有Cell的高度,如果有1W个Cell,那么- (CGFloat)tableView:(UITableView )tableView heightForRowAtIndexPath:(NSIndexPath )indexPath就会触发1W次,然后才显示内容。不过在iOS7以后,提供了一个新方法可以避免这1W次调用,它就是- (CGFloat)tableView:(UITableView )tableView estimatedHeightForRowAtIndexPath:(NSIndexPath )indexPath。要求返回一个Cell的估计值,实现了这个方法,那只有显示的Cell才会触发计算高度的protocol. 由于systemLayoutSizeFittingSize需要cell的一个实例才能计算,所以这儿用一个成员变量存一个Cell的实列,这样就不需要每次计算Cell高度的时候去动态生成一个Cell实例,这样即方便也高效也少用内存,可谓一举三得。
  • 声明一个存计算Cell高度的实例变量
 @property (nonatomic, strong) UITableViewCell *prototypeCell;
  • 初始化prototypeCell
self.prototypeCell = [self.tableView dequeueReusableCellWithIdentifier:@"C1"];
  • 计算Cell高度的实现
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
C1 *cell = (C1 *)self.prototypeCell;
cell.t.text = [self.tableData objectAtIndex:indexPath.row];
CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
NSLog(@"h=%f", size.height + 1); return 1 + size.height;
}
  • UITableViewCell的高度要比它的contentView要高1,也就是它的分隔线的高度

Manual Layout

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
C3 *cell = [self.tableView dequeueReusableCellWithIdentifier:@"C3"];
cell.t.text = [self.tableData objectAtIndex:indexPath.row];
[cell.t sizeToFit]; return cell; }
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
C3 *cell = (C3 *)self.prototypeCell;
NSString *str = [self.tableData objectAtIndex:indexPath.row];
cell.t.text = str;
CGSize s = [str calculateSize:CGSizeMake(cell.t.frame.size.width, FLT_MAX) font:cell.t.font];
CGFloat defaultHeight = cell.contentView.frame.size.height;
CGFloat height = s.height > defaultHeight ? s.height : defaultHeight;
NSLog(@"h=%f", height);
return 1 + height; }
// NSString的类别
- (CGSize)calculateSize:(CGSize)size font:(UIFont *)font {
CGSize expectedLabelSize = CGSizeZero;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) {
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
NSDictionary *attributes = @{NSFontAttributeName:font, NSParagraphStyleAttributeName:paragraphStyle.copy};
expectedLabelSize = [self boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size; } else { expectedLabelSize = [self sizeWithFont:font constrainedToSize:size lineBreakMode:NSLineBreakByWordWrapping]; }
return CGSizeMake(ceil(expectedLabelSize.width), ceil(expectedLabelSize.height));
}

UITextView in UITableViewCell

Auto Layout - 计算高度的代码

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
C2 *cell = (C2 *)self.prototypeCell;
cell.t.text = [self.tableData objectAtIndex:indexPath.row];
CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
CGSize textViewSize = [cell.t sizeThatFits:CGSizeMake(cell.t.frame.size.width, FLT_MAX)];
CGFloat h = size.height + textViewSize.height; h = h > 89 ? h : 89; //89是图片显示的最低高度, 见xib
NSLog(@"h=%f", h);
return 1 + h; }

说明:通过sizeThatFits:计算的UITextView的高度(这是计算UITextView内容全部显示时的方法),然后加上systemLayoutSizeFittingSize:返回的高度。为什么要这样呢? 因为UITextView内容的高度不会影响systemLayoutSizeFittingSize计算。 > 此图中距顶的约束是10, 距底的约束8, 距左边约束是87,距右边的约束是13, 那么systemLayoutSizeFittingSize:返回的CGSize为height等于19, size等于100. 它UITextView的frame是不影响systemLayoutSizeFittingSize:的计算。所以,需要加上textViewSize.height

Manual Layout

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
C4 *cell = [self.tableView dequeueReusableCellWithIdentifier:@"C4"];
cell.t.text = [self.tableData objectAtIndex:indexPath.row];
[cell.t sizeToFit];
return cell; }
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
C4 *cell = (C4 *)self.prototypeCell;
NSString *str = [self.tableData objectAtIndex:indexPath.row];
cell.t.text = str;
CGSize s = [cell.t sizeThatFits:CGSizeMake(cell.t.frame.size.width, FLT_MAX)];
CGFloat defaultHeight = cell.contentView.frame.size.height;
CGFloat height = s.height > defaultHeight ? s.height : defaultHeight;
return 1 + height; }

动态计算UITableViewCell高度的更多相关文章

  1. 转:动态计算UITableViewCell高度详解

    转自:http://www.cocoachina.com/industry/20140604/8668.html   不知道大家有没有发现,在iOS APP开发过程中,UITableView是我们显示 ...

  2. 动态计算UITableViewCell高度详解 (转)

    感觉挺有用的一篇文章,分析了4种解决方案.回头测试之.如果有别的方案,我会在后面补上. 原文地址:http://www.ifun.cc/blog/2014/02/21/dong-tai-ji-suan ...

  3. 动态计算UITableViewCell高度详解

    本文将介绍四种情况下UITableViewCell的计算方式,分别是: Auto Layout with UILabel in UITableViewCell Auto Layout with UIT ...

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

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

  5. 动态计算Label高度

    //1.设置该label的numberOfLines为0 self.titleLabel.numberOfLines = 0;    //2.字体的设置要与之前相同 NSDictionary * at ...

  6. 根据文字动态计算Label高度或宽度

    //根据已知的label宽度计算文字高度 CGRect rect = [reson boundingRectWithSize:CGSizeMake(label_W, 0) options:NSStri ...

  7. swift - 动态计算文本高度

        func heightOfCell(text : String) -> CGFloat {        let attributes = [NSFontAttributeName:UI ...

  8. iOS学习之根据文本内容动态计算文本框高度的步骤

    在视图加载的过程中,是先计算出frame,再根据frame加载视图的,所以在设计计算高度的方法的时候,设计成加号方法; //首先给外界提供计算cell高度的方法 + (CGFloat)heightFo ...

  9. UITableViewCell 高度自适应

    UITableViewCell 高度自适应一直是我们做动态Cell高度时遇到的最烦躁的问题,Cell动态高度计算可以去看看sunny的这篇文章介绍,今天主要和大家分享下我在使用systemLayout ...

随机推荐

  1. 解决在配置Oracle数据库连接错误问题

    项目开发使用的Oracle,但是使用了不同的版本的Oracle数据库.然后自己在电脑上安装了2个连接客户端,版本分别是: 10.2.0 12.1.0 用Toad for Oracle 9.0的时候,我 ...

  2. Java 8新特性-5 内建函数式接口

    在之前的一片博文 Lambda 表达式,提到过Java 8提供的函数式接口.在此文中,将介绍一下Java 8四个最基本的函数式接口 对于方法的引用,严格来讲都需要定义一个接口.不管我们如何操作实际上有 ...

  3. geotrellis使用(十九)spray-json框架介绍

    Geotrellis系列文章链接地址http://www.cnblogs.com/shoufengwei/p/5619419.html 目录 前言 spray-json简介 spray-json使用 ...

  4. Spring学习笔记--环境搭建和初步理解IOC

    Spring框架是一个轻量级的框架,不依赖容器就能够运行,像重量级的框架EJB框架就必须运行在JBoss等支持EJB的容器中,核心思想是IOC,AOP,Spring能够协同Struts,hiberna ...

  5. T-SQL简单查询语句

    简单查询: 1.最简单查询(查所有数据)select * from 表名: 注:* 代表所有列select * from info 2.查询指定列select code,name from info ...

  6. JS几种排序算法

    一.冒泡排序 var bubble = function(arr){ ;i<;i++){ ;j<-i;j++){ ]){ temp = arr[j]; arr[j] = arr[j+]; ...

  7. 加入一个线程:join

    在启动一个线程之后调用该线程的join()方法,会使该线程先执行,该线程执行完成后,再执行调用该线程的线程. 例如如下的任务: public class LiftOff extends Thread ...

  8. iOS的一些面试题分析总结(1)

    本篇主要说一下多线程的东西,因为东西比较多,所以直接拿出一整个篇幅来说它了. 3. 多线程的底层实现? 1.先说一下什么是进程,什么是线程.什么是多线程. 进程是资源分配的单位,线程是调度运行的基本单 ...

  9. [转]DbFirst数据验证

    转自:Data Validate 之 Data Annotation 什么是Data Annotation ? 如何使用 ? 自定义Validate Attribute EF  Db first中使用 ...

  10. Java中,方法的重写、重载的区别,以及多态的实例

    首先我们要明白什么是重写和重载 重写(override):子类方法覆盖了父类的方法.    (类与类之间继承的关系) 例:父类代码 public class Deng { public void Qi ...