6

我一直在寻找关于如何将自动布局添加到 UITableView 的明确答案。到目前为止,我的代码如下所示:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UINib *nib = [UINib nibWithNibName:@"HomeHeaderView" bundle:nil];
    UIView *headerView = (UIView *)[nib instantiateWithOwner:self options:nil][0];
    [headerView.layer setCornerRadius:6.0];
    [headerView setTranslatesAutoresizingMaskIntoConstraints:NO];

//    NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(headerView);
//    NSMutableArray *headerConstraints = [[NSMutableArray alloc] init];
//    [headerConstraints addObject:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[headerView]-|" options:0 metrics:nil views:viewsDictionary]];
//        [headerConstraints addObject:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[headerView]-|" options:0 metrics:nil views:viewsDictionary]];
//    [self.actionsTableView addConstraints:headerConstraints];
//    [self.view addSubview:headerView];
    tableView.tableHeaderView = headerView;
    [headerView layoutSubviews];

    NSLayoutConstraint *centerX = [NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0];
    NSLayoutConstraint *centerY = [NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0];
    NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:1 constant:300];
    NSLayoutConstraint *height = [NSLayoutConstraint constraintWithItem:headerView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:1 constant:90];
    [self.view addConstraints:@[centerX, centerY, width, height]];

    return headerView;
}

我基本上有一个用于我的标题视图的笔尖文件,我想将该笔尖放在我的 UITableViewHeader 中。我希望它在纵向和横向上相应地增长和缩小。老实说,我不确定我是否正确设置了约束。我不确定我toItem的应该是视图控制器的视图,还是 tableview 本身。

我也不知道是否应该将 headerview 作为子视图添加到视图控制器的视图或 tableview 本身。

或者,我不确定设置 tableView.tableHeaderView = headerView 是否足够。

我真的不知道这样的最佳实践是什么。我不确定这一切是否也可以在 IB 中完成。目前,使用您看到的代码,我收到此错误:

'Auto Layout still required after executing -layoutSubviews. UITableView's implementation of -layoutSubviews needs to call super.'

正是因为那个错误,我添加了[headerView layoutSubviews]

对此有什么想法?提前致谢!

4

3 回答 3

3

真正的问题是您viewForHeaderInSection:对表格的headerView. 他们是无关的。

前者是的标题。您从委托方法返回视图。

后者是的标题。您设置视图,可能在您的viewDidLoad.

约束以正常方式运行。但它们应该只是对其子视图的内部约束。在您形成它时,该视图不在您的界面中。而且它的大小和位置在当时并不取决于你。如果是节标题,它将自动调整大小以正确适应(根据表格的宽度和表格或委托对标题高度的声明)。如果它是表头,你可以给它一个绝对高度,但它的宽度会被调整到正确的大小。

这是一个完整的示例,它构造了一个在其子视图上具有内部约束的节标题。

- (UIView *)tableView:(UITableView *)tableView 
        viewForHeaderInSection:(NSInteger)section {
    UITableViewHeaderFooterView* h =
        [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"Header"];
    if (![h.tintColor isEqual: [UIColor redColor]]) {
        h.tintColor = [UIColor redColor];
        h.backgroundView = [UIView new];
        h.backgroundView.backgroundColor = [UIColor blackColor];
        UILabel* lab = [UILabel new];
        lab.tag = 1;
        lab.font = [UIFont fontWithName:@"Georgia-Bold" size:22];
        lab.textColor = [UIColor greenColor];
        lab.backgroundColor = [UIColor clearColor];
        [h.contentView addSubview:lab];
        UIImageView* v = [UIImageView new];
        v.tag = 2;
        v.backgroundColor = [UIColor blackColor];
        v.image = [UIImage imageNamed:@"us_flag_small.gif"];
        [h.contentView addSubview:v];
        lab.translatesAutoresizingMaskIntoConstraints = NO;
        v.translatesAutoresizingMaskIntoConstraints = NO;
        [h.contentView addConstraints:
         [NSLayoutConstraint 
          constraintsWithVisualFormat:@"H:|-5-[lab(25)]-10-[v(40)]"
          options:0 metrics:nil views:@{@"v":v, @"lab":lab}]];
        [h.contentView addConstraints:
         [NSLayoutConstraint 
          constraintsWithVisualFormat:@"V:|[v]|"
           options:0 metrics:nil views:@{@"v":v}]];
        [h.contentView addConstraints:
         [NSLayoutConstraint
          constraintsWithVisualFormat:@"V:|[lab]|"
           options:0 metrics:nil views:@{@"lab":lab}]];
    }
    UILabel* lab = (UILabel*)[h.contentView viewWithTag:1];
    lab.text = self.sectionNames[section];
    return h;
}
于 2013-09-17T20:09:27.337 回答
3

我发现matt 提供的解决方案可能并不完美,因为他正在将自定义视图和约束添加到UITableViewHeaderFooterView's contentView. 这总是在运行时导致自动布局警告:Unable to simultaneously satisfy constraints当我们想要动态标题高度时。

我不确定原因,但我们可以假设 iOS 添加了一些额外的约束来contentView设置该视图的固定宽度和高度。运行时生成的警告告诉我们手动添加的约束不能满足这些约束,这很明显,因为我们的约束应该拉伸标题视图,以便子视图可以适应它。

解决方案很简单 - 不要使用UITableViewHeaderFooterView's contentView,只需将您的子视图直接添加到UITableViewHeaderFooterView. 我可以确认它在 iOS 8.1 上没有任何问题。如果您想添加多个视图并更改标题的背景颜色,请考虑添加UIView填充标题视图(感谢 AutoLayout 约束),然后添加您希望对该视图拥有的所有子视图(我称之为customContentView)。这样我们就可以避免任何 AutoLayout 问题并在UITableView.

于 2014-12-03T20:42:13.797 回答
3

这是一个巧妙的解决方案:

可选:initWithStyle:UITableViewStyleGrouped 防止浮动 tableViewHeader

做两个属性,标签只是为了演示:

@property (nonatomic, strong, readwrite) UIView *headerView;
@property (nonatomic, strong, readwrite) UILabel *headerLabel;

在 viewDidLoad 中设置所有内容:

self.headerView = [[UIView alloc] initWithFrame:CGRectZero];
self.headerLabel = [[UILabel alloc] init];
self.headerLabel.text = @"Test";
self.headerLabel.numberOfLines = 0; //unlimited
self.headerLabel.textAlignment = NSTextAlignmentCenter;
self.headerLabel.translatesAutoresizingMaskIntoConstraints = NO; //always set this to NO when using AutoLayout
[self.headerView addSubview:self.headerLabel];

NSString *horizontalFormat = @"H:|-[headerLabel]-|";
NSArray *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:horizontalFormat options:0 metrics:nil views:@{@"headerLabel":self.headerLabel}];
[self.headerView addConstraints:horizontalConstraints];

NSString *verticalFormat = @"V:|-[headerLabel]-|";
NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:verticalFormat options:0 metrics:nil views:@{@"headerLabel":self.headerLabel}];
[self.headerView addConstraints:verticalConstraints];

在 viewForHeaderInSection 中:

return self.headerView;

在 heightForHeaderInSection 中:

self.headerLabel.preferredMaxLayoutWidth = tableView.bounds.size.width;
return [self.headerView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
于 2015-09-14T12:04:18.523 回答