iOS 8 - 最初从视图中隐藏 UITableView 的 headerView
iOS 8 - Initially hide a UITableView's headerView from view
就像在本机 iOS 邮件应用程序中一样,当我将 UITableViewController 推到 UINavigationController 上时,我想让 UITableView 最初看起来略微向下滚动,从而掩盖其 header在导航控制器的导航栏下方查看。
同时,即使所有单元格的高度都小于 table 视图的高度,用户也应该可以上下滚动以明确显示或隐藏header 再次查看。
从这个逻辑来看,对于这个实现似乎有两个考虑因素:
1) 确保 table 视图的最小内容大小至少为 table 视图框架的高度 + header 视图的高度。
2) 当 table 视图最初呈现时,内容偏移量增加 header 视图的高度。
我尝试手动设置 'viewWillAppear' 中 table 视图的 contentOffset 和 contentSize 属性,但这似乎没有效果(table 视图可能是在那之后重新加载)。尝试在 'viewDidAppear' 中设置它们会起作用,但为时已晚,因为只有在 'push' 动画完成后才会调用它。
虽然以前的 iOS 版本已经问过此类问题,但我无法让它们中的任何一个在 iOS 8 中工作。此外,它们都涉及更改偏移量,但不是 table 视图的 contentSize。
有人在 iOS 7 and/or 8 之前遇到过这种行为吗?
更新 - (30/1/2015)
好的。昨晚这对我来说不太好,所以我又玩了一次,我找到了一个更好更干净的解决方案。
我发现 UITableViewController
的 tableView
属性 不是 readonly
。因此,在 UITableView
子类中简单地管理 contentSize
属性 然后将该子类分配回 UITableViewController
.
实际上更有意义
@implementation TOCustomTableView
- (void)setContentSize:(CGSize)contentSize
{
CGFloat scrollInset = self.contentInset.top + self.contentInset.bottom;
CGFloat height = (CGRectGetHeight(self.bounds) - scrollInset) + CGRectGetHeight(self.tableHeaderView.frame);
contentSize.height = MAX(height, contentSize.height);
[super setContentSize:contentSize];
}
@end
---
@implementation TOCustomTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView = [[TOCustomTableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
}
@end
这样,table 视图的最小值 contentSize
始终明确设置为 table 视图的高度 + headerView 大小,从而实现零抖动的预期效果。 :)
原答案
trick14 为我指明了正确的方向。所以我最终得到了正确运行的代码。
- (void)resetTableViewInitialOffset
{
CGPoint contentOffset = self.tableView.contentOffset;
contentOffset.y = self.tableView.contentInset.top + CGRectGetHeight(self.headerView.frame);
self.tableView.contentOffset = contentOffset;
}
- (void)resetTableViewContentSize
{
CGSize contentSize = self.tableView.contentSize;
CGFloat scrollInset = self.tableView.contentInset.top + self.tableView.contentInset.bottom;
CGFloat height = (CGRectGetHeight(self.view.bounds) - scrollInset) + CGRectGetHeight(self.headerView.frame);
contentSize.height = MAX(height, contentSize.height);
self.tableView.contentSize = contentSize;
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
if (!self.headerBarInitiallyHidden) {
[self resetTableViewContentSize];
[self resetTableViewInitialOffset];
self.headerBarInitiallyHidden = YES;
}
}
我还确保每次在 table 视图上执行 'reloadData' 时调用 'resetTableViewContentSize'。
就像在本机 iOS 邮件应用程序中一样,当我将 UITableViewController 推到 UINavigationController 上时,我想让 UITableView 最初看起来略微向下滚动,从而掩盖其 header在导航控制器的导航栏下方查看。
同时,即使所有单元格的高度都小于 table 视图的高度,用户也应该可以上下滚动以明确显示或隐藏header 再次查看。
从这个逻辑来看,对于这个实现似乎有两个考虑因素:
1) 确保 table 视图的最小内容大小至少为 table 视图框架的高度 + header 视图的高度。
2) 当 table 视图最初呈现时,内容偏移量增加 header 视图的高度。
我尝试手动设置 'viewWillAppear' 中 table 视图的 contentOffset 和 contentSize 属性,但这似乎没有效果(table 视图可能是在那之后重新加载)。尝试在 'viewDidAppear' 中设置它们会起作用,但为时已晚,因为只有在 'push' 动画完成后才会调用它。
虽然以前的 iOS 版本已经问过此类问题,但我无法让它们中的任何一个在 iOS 8 中工作。此外,它们都涉及更改偏移量,但不是 table 视图的 contentSize。
有人在 iOS 7 and/or 8 之前遇到过这种行为吗?
更新 - (30/1/2015)
好的。昨晚这对我来说不太好,所以我又玩了一次,我找到了一个更好更干净的解决方案。
我发现 UITableViewController
的 tableView
属性 不是 readonly
。因此,在 UITableView
子类中简单地管理 contentSize
属性 然后将该子类分配回 UITableViewController
.
@implementation TOCustomTableView
- (void)setContentSize:(CGSize)contentSize
{
CGFloat scrollInset = self.contentInset.top + self.contentInset.bottom;
CGFloat height = (CGRectGetHeight(self.bounds) - scrollInset) + CGRectGetHeight(self.tableHeaderView.frame);
contentSize.height = MAX(height, contentSize.height);
[super setContentSize:contentSize];
}
@end
---
@implementation TOCustomTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView = [[TOCustomTableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
}
@end
这样,table 视图的最小值 contentSize
始终明确设置为 table 视图的高度 + headerView 大小,从而实现零抖动的预期效果。 :)
原答案
trick14 为我指明了正确的方向。所以我最终得到了正确运行的代码。
- (void)resetTableViewInitialOffset
{
CGPoint contentOffset = self.tableView.contentOffset;
contentOffset.y = self.tableView.contentInset.top + CGRectGetHeight(self.headerView.frame);
self.tableView.contentOffset = contentOffset;
}
- (void)resetTableViewContentSize
{
CGSize contentSize = self.tableView.contentSize;
CGFloat scrollInset = self.tableView.contentInset.top + self.tableView.contentInset.bottom;
CGFloat height = (CGRectGetHeight(self.view.bounds) - scrollInset) + CGRectGetHeight(self.headerView.frame);
contentSize.height = MAX(height, contentSize.height);
self.tableView.contentSize = contentSize;
}
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
if (!self.headerBarInitiallyHidden) {
[self resetTableViewContentSize];
[self resetTableViewInitialOffset];
self.headerBarInitiallyHidden = YES;
}
}
我还确保每次在 table 视图上执行 'reloadData' 时调用 'resetTableViewContentSize'。