使用自动布局,IB和字体大小时,表格标题视图高度错误

我正在尝试为我的uiTableView创build一个头部视图(不是部分头部,我已经有了这些头部视图)。我已经在界面构build器中设置了一个XIB。 所有的连接都连接起来,它运行得非常漂亮…除了桌子没有足够的空间! 我的问题是,表顶部重叠了表头的一点点。

我的XIB设置了所有button的自动布局,IB很高兴约束不会冲突/不明确。 该视图被设置为自由forms的大小,在我的情况下结束了320 x 471.然后在视图的约束,我为相同的视图设置一个固有的大小。

现在,这完美地与我的表。 一切看起来不错。 但是,如果我用代码手动更改标题视图中的任何字体,则布局将使视图变大,并最终到达我的表格下方。

任何想法如何让tableviewcontroller设置字体和大小后,为标题视图留出足够的空间? 我希望我能解释这一点。

这个想法是通过systemLayoutSizeFittingSize:targetSize来计算标题的高度。

返回满足其约束的视图的大小。 确定考虑到所有约束和子视图的最佳大小。

在改变标题的高度之后,有必要重新分配tableHeaderView属性来调整表格单元格。

基于这个答案: 在UITableView中使用自动布局来实现dynamic单元格布局和可变行高

 - (void)sizeHeaderToFit { UIView *header = self.tableView.tableHeaderView; [header setNeedsLayout]; [header layoutIfNeeded]; CGFloat height = [header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; CGRect frame = header.frame; frame.size.height = height; header.frame = frame; self.tableView.tableHeaderView = header; } 

当我尝试将我的表格视图标题设置为使用界面生成器自定义的自定义视图时,遇到了类似的问题。

当我这样做的时候,我会发现它会被一个标题所遮盖。

我的工作涉及使用“虚拟视图”作为表头视图,然后将我的自定义视图添加到该虚拟视图作为子视图。 我认为这允许自动布局根据约束和包含视图的框架configuration外观。 这可能不像vokilam的解决scheme那么优雅,但对我来说却很有用。


 CGRect headerFrame = CGRectMake(0, 0, yourWidth, yourHeight); UIView *tempView = [[UIView alloc] initWithFrame:headerFrame]; [tempView setBackgroundColor:[UIColor clearColor]]; YourCustomView *customView = [[YourCustomView alloc] initWithFrame: headerFrame]; [tempView addSubview:movieHeader]; self.tableView.tableHeaderView = tempView; 

因为你的tableHeaderView是自动布局xib的自动布局,所以你自定义的headerViewsuperViewconstraintsheaderView 。你应该添加自定义headerViewconstraints

1.in viewDidLLoad将自定义的headerView分配给tableView的tableHeaderView

  - (void)viewDidLoad { [super viewDidLoad]; UIView *yourHeaderView = [[[NSBundle mainBundle] loadNibNamed:@"yourHeaderView" owner:nil options:nil] objectAtIndex:0]; //important:turn off the translatesAutoresizingMaskIntoConstraints;apple documents for details yourHeaderView.translatesAutoresizingMaskIntoConstraints = NO; self.tableView.tableHeaderView = yourHeaderView; } 

2.in – (void)updateViewConstraints,添加自定义headerView的基本约束

 - (void)updateViewConstraints { NSDictionary *viewsDictionary = @{@"headerView":yourHeaderView}; NSArray *constraint_V = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[headerView(121)]" options:0 metrics:nil views:viewsDictionary]; NSArray *constraint_H = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[headerView(320)]" options:0 metrics:nil views:viewsDictionary]; [self.headerView addConstraints:constraint_H]; [self.headerView addConstraints:constraint_V]; NSArray *constraint_POS_V = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[headerView]" options:0 metrics:nil views:viewsDictionary]; NSArray *constraint_POS_H = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[headerView]" options:0 metrics:nil views:viewsDictionary]; [self.tableView addConstraints:constraint_POS_V]; [self.tableView addConstraints:constraint_POS_H]; [super updateViewConstraints]; } 

好! PS:这是相关的文档: 调整视图控制器的视图

什么解决了我的问题是这样的:

 override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() sizeHeaderToFit() } private func sizeHeaderToFit() { if let headerView = tableView.tableHeaderView { headerView.setNeedsLayout() headerView.layoutIfNeeded() let height = headerView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height var newFrame = headerView.frame // Needed or we will stay in viewDidLayoutSubviews() forever if height != newFrame.size.height { newFrame.size.height = height headerView.frame = newFrame tableView.tableHeaderView = headerView } } } 

我发现这个解决scheme的地方,像魅力工作,我不记得在哪里。

我发现vokilam的答案很好。 这是他在Swift中的解决scheme。

 func sizeHeaderToFit() { guard let header = tableView.tableHeaderView else { return } header.setNeedsLayout() header.layoutIfNeeded() let height = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height header.frame.size.height = height tableView.tableHeaderView = header } 

在我的情况systemLayoutSizeFittingSize返回不正确的大小,因为其中一个子视图使用宽高比(宽高比)4:1约束。

将其更改为恒定高度约束值(100)后,开始按预期工作。

结合@SwiftArchitect,@ vokilam和@mayqiyue的答案,并使用编程创build的tableHeaderView而不是一个笔尖(虽然,我没有看到任何理由为什么它不应该与一个笔尖),并在iOS 10.x / Xcode 8.2.1,这是我的工作:

在视图控制器的-viewDidLoad或 – init方法中创build视图,或者在使用表视图的任何位置创build视图:

 MyCustomTableHeaderView *myCustomTableHeaderView = [[MyCustomTableHeaderView alloc] init]; // Don't set its frame myCustomTableHeaderView.translatesAutoresizingMaskIntoConstraints = NO; self.myTableView.tableHeaderView = myCustomTableHeaderView; self.myCustomTableHeaderView = myCustomTableHeaderView; // We set and update our constraints in separate methods so we store the table header view in a UIView property to access it later 

无论你在哪里设置自定义标题视图的约束(可以在`updateConstraints中,但是这个方法可以被多次调用):

 // We use Pure Layout in our project, but the workflow is the same: // Set width and height constraints on your custom view then pin it to the top and left of the table view // Could also use VFL or NSLayoutConstraint methods [self.myCustomTableHeaderView autoSetDimension:ALDimensionWidth toSize:CGRectGetWidth(self.superview.frame)]; // Width set to tableview's width [self.myCustomTableHeaderView autoSetDimension:ALDimensionHeight toSize:height]; // Whatever you want your height to be [self.myCustomTableHeaderView autoPinEdgeToSuperviewEdge:ALEdgeTop]; [self.myCustomTableHeaderView autoPinEdgeToSuperviewEdge:ALEdgeLeft]; // This is important [self.myCustomTableHeaderView layoutIfNeeded]; // We didn't need to call -setNeedsLayout or reassign our custom header view to the table view's tableHeaderView property again, as was noted in other answers 

其他答案指出我正确的方向,让tableHeaderView适当resize。 但是,我得到了标题和tableView单元格之间的差距。 这也可能导致您的单元格与您的标题重叠,具体取决于标题是否增长或变小。

我从这个去了:

  tableView.reloadData() let height = tableViewHeader.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height tableView.tableHeaderView?.frame.size.height = height 

为了修复间隙/重叠,我只需要将tableView.reloadData()移动到设置新高度之后而不是之前。

对此:

  let height = tableViewHeader.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height tableView.tableHeaderView?.frame.size.height = height tableView.reloadData() 

sizeHeaderToFitbuild议的sizeHeaderToFit不适合我。

有效的是@mayqiyue的修改版本,在viewDidLoad调用,有线高度,与表格视图等宽。

 // Anchor the headerview, and set width equal to superview NSDictionary *viewsDictionary = @{@"headerView":self.tableView.tableHeaderView, @"tableView":self.tableView}; [self.tableView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[headerView]" options:0 metrics:nil views:viewsDictionary]]; [self.tableView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[headerView]" options:0 metrics:nil views:viewsDictionary]]; [self.tableView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[headerView(==tableView)]" options:0 metrics:nil views:viewsDictionary]]; [self.tableView.tableHeaderView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[headerView(121)]" options:0 metrics:nil views:viewsDictionary]]; 

下面的代码已经为我工作: – 添加到你的UIView类 –

 - (instancetype)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { self.frame = CGRectMake(0, 0, self.frame.size.width, [[self class] height]); } return self; 

}

@ rmigneco答案为我工作,所以这里是它的迅速版本:

 let headerFrame = CGRectMake(0, 0, 100, 1); let tempView = UIView(frame: headerFrame); tempView.backgroundColor = UIColor.clearColor() let yourCustomView = CustomView(frame: headerFrame) tempView.addSubview(yourCustomView) self.tableView.tableHeaderView = tempView