首先,那些其他视图(表格视图的兄弟)是否严格位于表格视图的上方和下方?如果是这样,您是否考虑过让表格视图正常滚动,并将这些外部视图放在表格视图的页眉和页脚视图中?那么你就不需要滚动视图了。
其次,如果您还没有阅读Technical Note TN2154: UIScrollView And Autolayout,您可能想阅读。
第三,鉴于该技术说明中的信息,我可以想出一些方法来做你想做的事。最干净的可能是创建一个实现intrinsicContentSize 方法的UITableView 的子类。实现很简单:
@implementation MyTableView
- (CGSize)intrinsicContentSize {
[self layoutIfNeeded]; // force my contentSize to be updated immediately
return CGSizeMake(UIViewNoIntrinsicMetric, self.contentSize.height);
}
@end
然后让自动布局使用表格视图的固有内容大小。在滚动视图(包括表格视图)的子视图之间创建约束以进行布局,并确保滚动视图的所有四个边缘都有约束。
您可能需要在适当的时候将invalidateIntrinsicContentSize 发送到表格视图(当您添加或删除行或更改行的高度时)。您可能只需覆盖MyTableView 中的适当方法即可。例如。在-endUpdates、-reloadData、- insertRowsAtIndexPaths:withRowAnimation:等中做[self invalidateIntrinsicContentSize]。
这是我的测试结果:
滚动视图具有浅蓝色背景。顶部的红色标签和底部的蓝色标签是滚动视图中表格视图的兄弟。
这是我测试中视图控制器的完整源代码。没有xib文件。
#import "ViewController.h"
#import "MyTableView.h"
@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
@end
@implementation ViewController
- (void)loadView {
UIView *view = [[UIView alloc] init];
self.view = view;
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
scrollView.backgroundColor = [UIColor cyanColor];
[view addSubview:scrollView];
UILabel *topLabel = [[UILabel alloc] init];
topLabel.translatesAutoresizingMaskIntoConstraints = NO;
topLabel.text = @"Top Label";
topLabel.backgroundColor = [UIColor redColor];
[scrollView addSubview:topLabel];
UILabel *bottomLabel = [[UILabel alloc] init];
bottomLabel.translatesAutoresizingMaskIntoConstraints = NO;
bottomLabel.text = @"Bottom Label";
bottomLabel.backgroundColor = [UIColor blueColor];
[scrollView addSubview:bottomLabel];
UITableView *tableView = [[MyTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
tableView.translatesAutoresizingMaskIntoConstraints = NO;
tableView.dataSource = self;
tableView.delegate = self;
[scrollView addSubview:tableView];
UILabel *footer = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 30)];
footer.backgroundColor = [UIColor greenColor];
footer.text = @"Footer";
tableView.tableFooterView = footer;
NSDictionary *views = NSDictionaryOfVariableBindings(
scrollView, topLabel, bottomLabel, tableView);
[view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:|[scrollView]|"
options:0 metrics:nil views:views]];
[view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"H:|[scrollView]|"
options:0 metrics:nil views:views]];
[view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:|[topLabel][tableView][bottomLabel]|"
options:0 metrics:nil views:views]];
[view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"H:|[topLabel]|"
options:0 metrics:nil views:views]];
[view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"H:|-8-[tableView]-8-|"
options:0 metrics:nil views:views]];
[view addConstraint:[NSLayoutConstraint
constraintWithItem:tableView attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:view attribute:NSLayoutAttributeWidth
multiplier:1 constant:-16]];
[view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"H:|[bottomLabel]|"
options:0 metrics:nil views:views]];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
}
cell.textLabel.text = [NSString stringWithFormat:@"Row %d", indexPath.row];
return cell;
}
@end