我现在一直在努力解决这个问题,我想确保我这样做是正确的。作为参考,我使用AutoLayout和Storyboard,它是一个仅限iOS7的应用程序。
我有一个带标题视图的UITableView,并且HeaderView的UI连接在故事板中。我在故事板中留下了标题,它包含一些元素,其中一个是不可滚动的UITextView。
以下是故事板中基本上看起来的截图:
我将标题视图的背景变暗为深灰色,因此它很突出。
UITextView的文本可以是动态的,因此其高度需要根据文本的大小而改变。但棘手的部分是表的标题视图也需要调整其高度,具体取决于文本的大小。我已经尝试了一些带有约束的不同东西,但它并没有真正正常工作(除非我禁用AutoLayout并以编程方式重新调整大小,我真的很想避免)。
当然,我希望尽可能使用尽可能少的代码。我并不依赖于使用表视图标题,尽管它可以很好地满足我的需求,因为我希望它和它包含的textview能够滚动下面的实际细节。但总而言之,如果有一种更简单的方法来实现这一目标(即使用uilabel),我将很乐意改变基础结构。
对方法的任何想法?没有找人帮助我的答案;如果可能的话,只是寻找一些好的起点。提前谢谢!
答案 0 :(得分:33)
前段时间我找到了新的解决方案,也许它需要调整动画并且是实验性的,但是,对于某些情况它很好,所以试一试:
-updateTableViewHeaderViewHeight
)-resetTableViewHeaderView
)以下是一些代码:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[self updateTableViewHeaderViewHeight];
}
/**
tableView's tableViewHeaderView contains wrapper view, which height is evaluated
with Auto Layout. Here I use evaluated height and update tableView's
tableViewHeaderView's frame.
New height for tableViewHeaderView is applied not without magic, that's why
I call -resetTableViewHeaderView.
And again, this doesn't work due to some internals of UITableView,
so -resetTableViewHeaderView call is scheduled in the main run loop.
*/
- (void)updateTableViewHeaderViewHeight
{
// get height of the wrapper and apply it to a header
CGRect Frame = self.tableView.tableHeaderView.frame;
Frame.size.height = self.tableHeaderViewWrapper.frame.size.height;
self.tableView.tableHeaderView.frame = Frame;
// this magic applies the above changes
// note, that if you won't schedule this call to the next run loop iteration
// you'll get and error
// so, I guess that's not a clean solution and could be wrapped in @try@catch block
[self performSelector:@selector(resetTableViewHeaderView) withObject:self afterDelay:0];
}
// yeah, guess there's something special in the setter
- (void)resetTableViewHeaderView
{
// whew, this could be animated!
[UIView beginAnimations:@"tableHeaderView" context:nil];
self.tableView.tableHeaderView = self.tableView.tableHeaderView;
[UIView commitAnimations];
}
所有这些在初始自动布局通过后无缝地工作。之后,如果您更改包装器的内容以使其获得不同的高度,则由于某种原因它不会起作用(猜测布局UILabel需要几个自动布局通道或其他东西)。我在下一次运行循环迭代中为ViewController的视图调度setNeedsLayout解决了这个问题。
我为此创建了示例项目:TableHeaderView+Autolayout。
答案 1 :(得分:0)
我建议以编程方式设置高度。 您可以使用boundingRectWithSize:options:context
计算文本视图的高度然后你只需设置tableView标题的框架。
答案 2 :(得分:-3)
如上所述,在UITableView中,标题的高度不受自动布局控制,而是由
控制-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
页脚高度由
设置-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
最后,单元格高度由
设置-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
tableview从故事板,XIB文件或代码加载单元格。它使用上述方法设置页眉,页脚和单元格的框架大小,并调整其视图大小以适应该空间。
了解自动布局不会更改这些大小非常重要,它只处理用于布置容器内视图的规则。
如果您的单元格/页眉/页脚使用静态大小,那么它非常简单。你只需锁定所有子视图的高度,将你的单元格设置为与你返回的高度相同的尺寸......并且一切看起来都应该如此。
动态单元格/页眉/页脚需要更多工作。
基本上,您需要在实际制作单元格/页眉/页脚之前告诉tableview大小,并确定所有子视图的大小。
您可以通过在cellForRowAtIndexPath和heightForRowAtIndexPath方法中设置断点来快速测试,首先调用高度。
对于动态tableviewcell高度,一个常见的技巧是在viewDidLoad中创建一个单元格并保存它以计算高度。然后当你到达heightForRowAtIndexPath或heightForHeaderInSection时,使用预先制作的单元格放入你将在最后一个单元格中使用的值,因为UILabels使用sizeWithFont(iOS 7之前版本)或boundingRectWithSize(iOS 7.0+),以及用于UITextViews的sizeThatFits。 (对于将来阅读此内容的任何人,请检查这些方法是否已被更新的内容替换)
因此,将您想要的文本放入虚拟单元格中,获取标签和文本视图的高度,在它们之间添加空格,并在完成后返回最终大小。
然后在cellForRowAtIndexPath或headerForSection中重做值的设置,但是在将要显示的实际单元格上。
如果您的高度计算与您的自动布局设置相匹配,那么一切都将完美地适合为其制作的空间。
如果要在已经绘制单元格或标题后更改单元格或标题的高度,则需要通过执行以下操作来更新表格视图:
[self.tableView beginUpdates];
// change the data that will cause cell height to be different in heightForCellAtIndexPath or which will change a header or footer height calculation
[self.tableView endUpdates];
这将导致tableview检查它的大小,并且只有在更改时才更新单元格或页眉/页脚。
答案 3 :(得分:-4)
表视图标题视图通过tableView:viewForHeaderInSection:delegate方法提供给表视图。
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
// create your header view here (read the docs on this method, there are some specific requirements)...
}
我不知道是否可以在故事板中设计标题视图;我想你必须使用单独的XIB文件或以编程方式这样做。
换句话说,如果您需要提供表视图标题视图,我认为您将在代码中创建约束。
另一方面,也许你真的不需要表视图标题视图。也许,你所追求的只是表视图上方的一个子视图,当用户滚动表时它不会移动。为此,您需要在IB中重新查看视图层次结构。现在你所谓的标题视图在表视图中。你不希望这样。
或者,因为看起来你正在使用静态单元格,所以你可以让顶部的静态单元格显示出你所谓的标题视图的外观。