iOS-Auto Layout[6]-UIScrollView And UITableViewCell

本文讲解了Auto Layout中两类特殊View, UIScrollView & UITableViewCell。

UIScollView

UIScrollView是比较特殊的控件,其有Content Size需要与Constraints进行计算,当在UIScrollView中加入View时,需要注意这一点。

举例:

定义好UIScrollView在SuperView的Constraints后,往UIScrollView中加入一个View,设置其Constraints为:

1
2
3
4
view.leading = scollView.leading + 50;
view.trailing = scollView.trailing - 50;
view.top = scollView.top + 50;
view.bottom = scollView.bottom - 50;

一般情况下,这样的Constraints,AutoLayout已经可以计算出其布局了,但是在UIScrollView中,由于view没有设置width和height,其无法计算出Content Size,所以会报异常:

AutoLayout-UIScrollView-Error

加上以下Constraints即可:

1
2
view.width = 300;
view.height = 100;

这是,Content Size可以计算出为:(400, 200)。

对于,UILabel, UIImageView这种需要在运行时决定其大小的控件,可以在IB中设计时,将其Intrinsic Size属性设置为Placeholder,并设置宽高:

AutoLayout-UIScrollView-Placeholder

这里的Intrinsic Size只会在设计时有效,在运行时可以重新设置其大小。

UITableViewCell

在AutoLayout中,有时候需要UITableViewCell的高度参与Constraints运算,但是其高度是通过回调设置的:

1
tableView:heightForRowAtIndexPath:

为了满足计算的需要,可以设置一个估算的高度,AutoLayout将会根据这个估算的高度来计算UITableViewCell最后的真实高度:

1
2
tableView.estimatedRowHeight = 85.0;
tableView.rowHeight = UITableViewAutomaticDimension;

另外,系统会根据该估算高度来计算一些控件的高度,例如ScrollBar,所以,估算高度要尽可能的精确。

为了正确地计算UITableViewCell的真实高度,需要定义好Subviews的Constraints:

Chain-of-Views-and-Constraints

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"123" forIndexPath:indexPath];
if(!cell){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"123"];
}
UIView *testView = [UIView new];
testView.backgroundColor = [UIColor greenColor];
testView.translatesAutoresizingMaskIntoConstraints = NO;
[cell addSubview:testView];
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|-[TestView]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:@{@"TestView":testView}]];
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[TestView(>=60)]-|" options:NSLayoutFormatAlignAllTop metrics:nil views:@{@"TestView":testView}]];
return cell;
}

需要注意的点:

  • 不能改变已包含的控件的Constraints,例如textLabel,detailTextLabel和imageView,但可以建立与其相关的Constraints;
  • 可以建立与UITableViewCell的ContentView相关的Constraints;
  • 可以建立与UITableViewCell的Bounds相关的Constraints;