上一篇介绍了AutoLayout的三个属性,后来发现其实和UITableViewCell动态高度的学习关系不大。不过还是有用的,因为AutoLayout涉及到比较复杂的布局,就肯定会用到那三个属性。废话不多说,今天就来学习一下UITableViewCell的动态计算高度问题。这篇的方法仅适用IOS8以上的系统,稍后在写一篇通用的。
计算Cell高度这个问题,苹果终于在IOS8时帮我们做了,也就是self-sizing-cells这个概念。用起来也是很简单的。
1.你的Cell要使用AutoLayout来布局约束这是必须的;
2.设置tableview的estimatedRowHeight为一个非零值,这个属性是设置一个预估的高度值,不用太精确。
3.设置tableview的rowHeight属性为UITableViewAutomaticDimension
就是下面这两行代码
tableView.estimatedRowHeight = 37.0;
tableView.rowHeight = UITableViewAutomaticDimension;
接下来你只需要用AutoLayout布局好Cell,一切就都交给苹果吧。下面看一下例子:
新建一个Master-detail的项目,模版是包括增删当前时间的,我们不需要,稍微改一下,显示一些静态数据就好。记得加上上面的两行代码,修改之后viewDidLoad代码如下:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.tableView.estimatedRowHeight = 37.0;
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.objects = [NSMutableArray arrayWithArray:@[@"In iOS 8, Apple introduces a new feature for UITableView known as Self Sizing Cells. This is seriously one of the most exciting features for the new SDK. Prior to iOS 8, if you displayed dynamic content in table view with varied row, you need to calculate the row height on your own. In summary, here are the steps to implement when using self sizing cells",@"Add auto layout constraints in your prototype cell",@"Specify the estimatedRowHeight of your table view",@"Set the rowHeight of your table view to UITableViewAutomaticDimension",@"tableView.estimatedRowHeight = 36.0;",@"tableView.rowHeight = UITableViewAutomaticDimension;"]];
}
数据准备好了,接下来我们开始自定义Cell,新建UITableViewCell子类为
DemoTableViewCell,然后我们打开stroyboard。选择Master Scene中TableView的Cell,将Custom Class改成我们新建的DemoTableViewCell。TableViewCell的style改成Custom。把TableView的Row Height改的高一些。我们现在Cell左边放一个图片,设置他的约束如图:
接着右边放一个Label,设置约束如图:
然后打开Assistant editor 把Label连到DemoCell中。如图:
下面修改一下MasterViewController里面tableView的代理方法。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
DemoTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
cell.cellText.text = self.objects[indexPath.row];
return cell;
}
运行看下效果如图:
好吧,原谅我,忘记了一个重要的属性。返回storyboard,将Label的Lines设置成0,代码多行。如图:
运行看下效果
搞定了,和自己计算比起来简直方便太多。
接下来看看如果在原有的Label下面再加一个需要计算高度的Label会是什么效果(Label1,Label2)。这就会涉及到约束优先级的问题了。此时Label1的下边距约束对象应该又superview变成Label2,Label2的上边距约束对象应该是Label1,Label2的下边距约束对象是superview。看下修改后出现的问题
因为两个Label的高度都是不固定的,所以当Cell高度变大时需要设置谁去被拉伸,xcode推荐我们把Label1的抗拉伸优先级调小,我们按照推荐的来。运行一下看效果:
Label1被拉伸了。反过来修改Label1的抗拉伸优先级大于Label2后,Label2会被拉伸。仔细的观察了一下Cell的高度,发现其实Cell的高度是正确的,是Label高度的两倍,只是两个Label的高度出现了问题,我的想法是如果先按正确高度绘制Label1,然后在绘制Label2,就不会出现这个问题了。仔细一想这样不对,因为Label1的下边距和Label2的上边距是互相依靠的,这相当于两个Label的优先级应该一样才可以,谁高于谁都不能正确。但都一样的时候苹果又不是知道要拉伸的时候该拉伸谁。这时候只能把Label1和Label2的之间的关系拆开才行,决定加一个空的View在Cell中间试试,给View加了一个竖直居中的约束,固定高度为1,然后让两个Label都和View去产生约束,运行看下效果。
问题解决了。