iOS Xcode7 Xib 动态计算UITableViewCell高度详解

http://justsee.iteye.com/blog/2208725


不知道大家有没有发现,在iOS APP开发过程中,UITableView是我们显示内容常见的控件,本人觉得它是UIKit中最复杂的一个控件。今天要向大家介绍的就是如何动态计算UITableViewCell高度的一经验与技巧,在此做一些总结方便朋友们查阅。为了不让讲解空洞抽象,我还是用代码实例的方式进行讲解,这样更容易接收与学习。
  本文将介绍四种情况下UITableViewCell的计算方式,分别是:
1. Auto Layout with UILabel in UITableViewCell
2. Auto Layout with UITextView in UITableViewCell
3. Manual Layout with UILabel in UITableViewCell
4. Manual Layout with UITextView in UITableViewCell
5. 随UITextView高度动态改变Cell高度
 
首先创建一个Single Page的工程,我命名为CellHeightDemo
 
1. Auto Layout with UILabel in UITableViewCell
创建一个空的xib,命名为C1.xib, 然后拖入一个UITableViewCell控件。接着创建一个UITableViewCell的子类,命名为C1类。然后在C1.xib中,将与C1类进行关联。别给我说你不会关联,如果不会那看下图你就明白了。 
\

 
 
只需要在Class那里写入关联的类名C1即可。
 
还有由于UITableViewCell需要重用功能,所以我们还需要设置一个重用标识 


 
 
在Identifier那里写入重用标识C1,当然你也可以用任意字符。不过后面代码里需要这个字符。
 
接着我们来布局。用到了auto layout, 在此我不想介绍auto layout, 以后有时间再专门介绍,下图就是我布局 


 
 
这儿有两点需要说明:1. UILabel的属性Lines这儿设为了0表示显示多行。2. Auto Layout一定要建立完完整。
 
接着我们在UITableView中来使用我们自定义的UITableViewCell C1。
 
首先我们创建一个UITableViewController的子类T1ViewController, 接着在Main.storyboard中拖入一个UITableViewController,并关联T1ViewController。


 
 
一切都准备好了,那我们现在来写点代码,给UITableView加点料。
 
我们想要我们的UITableView使用C1.xib中自定义的Cell,那么我们需要向UITableView进行注册。
  1. UINib *cellNib = [UINib nibWithNibName:@"C1" bundle:nil]; 
  2. [self.tableView registerNib:cellNib forCellReuseIdentifier:@"C1"]; 
 
这样就进行注册了,接着我们还需要每行显示的数据,为了简单一点,我就声明了一个NSArray变量来存放数据。
  1. self.tableData = @[@"1\n2\n3\n4\n5\n6", @"123456789012345678901234567890", @"1\n2", @"1\n2\n3", @"1"]; 
 
现在实现UITableViewDataSource的protocol:
  1. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
  2.     // Return the number of rows in the section. 
  3.     return self.tableData.count; 
  4.   
  5. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
  6.     C1 *cell = [self.tableView dequeueReusableCellWithIdentifier:@"C1"]; 
  7.     cell.t.text = [self.tableData objectAtIndex:indexPath.row]; 
  8.     return cell; 
 
从self.tableData中的数据我们可以看到,每一个Cell显示的数据高度是不一样的,那么我们需要动态计算Cell的高度。由于是auto layout,所以我们需要用到一个新的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高度的实例变量:
  1. @property (nonatomic, strong) UITableViewCell *prototypeCell; 
 
然后初始化它:
  1. self.prototypeCell  = [self.tableView dequeueReusableCellWithIdentifier:@"C1"]; 
 
下面是计算Cell高度的实现:
  1. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
  2.     C1 *cell = (C1 *)self.prototypeCell; 
  3.     cell.t.text = [self.tableData objectAtIndex:indexPath.row]; 
  4.     CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; 
  5.     NSLog(@"h=%f", size.height + 1); 
  6.     return 1  + size.height; 
 
看了代码,可能你有点疑问,为何这儿要加1呢?笔者告诉你,如果不加1,结果就是错误的,Cell中UILabel将显示不正确。原因就是因为这行代码CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];由于是在cell.contentView上调用这个方法,那么返回的值将是contentView的高度,UITableViewCell的高度要比它的contentView要高1,也就是它的分隔线的高度。如果你不相信,那请看C1.xib的属性,比较下面两张图。 


 
 


 
 
发现没Cell的高度是127, 面contentView的高度是126, 这下明白了吧。
 
为了让读者看清楚,我将Cell中UILabel的背景色充为了light gray.下面是运行效果: 


 
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值