根据 UITableView 调整 UIScrollView 高度
Posted
技术标签:
【中文标题】根据 UITableView 调整 UIScrollView 高度【英文标题】:Adjust a UIScrollView height based on a UITableView 【发布时间】:2013-04-03 22:00:31 【问题描述】:我有一个 UIScrollView,它包含一个 UIView 和一个 UITableView。我的目标是调整 UIScrollView 的高度以允许我将 UIScrollView 的内容滚动到特定点。
这是我的观点:它在顶部有一个 UIView,在下面有一个 UITableView。
当我滚动时,我希望 UIView 在特定点停止,如下所示:
tableView 将能够继续滚动,但 UIView 将被锁定在原地,直到用户向上滚动并将 UIView 带回其原始状态。
我正在尝试做的一个主要示例是 ios 6 上的 AppStore.app。当您查看应用程序的详细信息时,详细信息、评论和相关的过滤器栏会移动到屏幕顶部并停止。我希望这一切都有意义。
谢谢
【问题讨论】:
【参考方案1】:我最终选择了一种更简单的方法。不敢相信我以前没见过这个。我创建了两个视图,一个用于 UITableView 的 tableHeaderView,另一个用于 viewForHeaderInSection。我希望始终保持可见的视图放置在 viewForHeaderInSection 方法中,而另一个视图放置在 tableHeaderView 属性中。我认为这是一种比使用滚动视图更简单的方法。我使用这种方法遇到的唯一问题是这两个视图中的所有 UIView 动画都不再动画。 这是我的代码。
[self.tableView setTableHeaderView:self.headerView];
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
return self.tableViewHeader;
【讨论】:
我相信这只适用于只有一个部分的 UITableView。【参考方案2】:将自己作为 UIScrollViewDelegate
添加到 UITableView 并实现 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
,这样如果您的视图处于初始位置,它们会执行以下操作:
- 您的 UITableView
将其大小设置为第二个状态:
[UIView animateWithDuration:.1f animations:^
CGRect theFrame = myView.frame;
theFrame.size.height += floatOfIncreasedHeight;
myView.frame = theFrame;
];
- 您的 UIView
为其垂直移动设置动画
[UIView animateWithDuration:3 delay:0 options:UIViewAnimationOptionCurveLinear animations:^(void)
view.center = CGPointMake(view.center.x , view.center.y + floatOfVerticalMovement);
completion:^(BOOL Finished)
view.center = CGPointMake(view.center.x , view.center.y - floatOfVerticalMovement);]
最后总是在委托中实现– scrollViewDidScrollToTop:
,这样你就知道可以动画回到初始状态(使用相同的技术倒过来)。
更新:
由于您的视图位于滚动视图内,如果您可以接受表格视图在起始位置部分超出范围(即,它不会更改大小,它只是滚动到视图中),则有一种更简单的方法:
使滚动视图框架大小与您的最终tableview
+ 您的初始(整个)视图一样大,并将其放置在 0,0(因此其最终部分将隐藏在屏幕之外)
scrollview.frame = CGRectMake(0,0,tableview.frame.size.width,tableview.frame.size.height + view.frame.size.height);
您使容器scrollview
的内容与整个表格视图 + 整个视图 + 滚动表格视图时您想要的视图数量一样大。
scrollview.contentSize = CGSizeMake(scrollview.frame.size.width, tableview.frame.size.height + view.frame.size.height + floatOfViewHeightIWantOutOfTheWay);
您将视图一个接一个地放置在滚动视图中,在表格视图之后留下所有额外的空白空间
view.frame = CGRectMake(0,0,view.frame.size.width, view.frame.size.height);
tableview.frame = CGRectMake(0,view.frame.size.height, tableview.frame.size.width, tableview.frame.size.height);
现在它应该可以工作了,因为 iOS 3
嵌套 scrolling
受支持
【讨论】:
我明白这一切是如何运作的,但我还是有点困惑。我的 UItableView 从 API 下载内容并且单元格都相应地调整大小,我将如何计算滚动视图和 tableView 的高度? 您不需要 uitableview 的内容大小,只需要它的框架(我们在您的第二个模型中看到的那个)。您可以在 uitableview 中拥有任意数量的行,因为它本身就是一个滚动视图。 如果您希望您的上视图在用户向上或向下滚动 Uitableview 时不碍事,我也没有得到。如果我的答案中的第二种方法按原样工作,如果它是关闭的,那么您仍然需要成为 tableview 委托和 scrollViewWillBeginDragging,您可以通过调用手动重新调整外部滚动视图 - scrollRectToVisible:animated: 我现在明白了。我希望第二个视图的浅灰色部分始终对用户可见。一旦你开始在 UITableView 中向下滚动,它就会向上滑动顶视图。查看应用的详细信息时,您可以在 App Store 应用中了解我的意思。 我的两种方法都可以实现。也许在第二种方法中,而不是使用 scrollwillbegindragging,您可以要求父滚动视图中的手势识别器延迟触摸开始/结束。 Apple 实现嵌套滚动视图的默认方式是包含的优先于容器,因此切换它可以解决您的问题,而无需跟踪每个初始滚动【参考方案3】:您可以通过正确设置 scrollView 的内容大小并保持 UITableView 的高度小于您的 viewcontroller 的高度来轻松实现这一点,使其适合顶部 UIView 和 UITableView 的底部...
另一种情况是将顶部视图分成两部分。 将滚动离开的部分和将可见的部分。
然后将滚动的部分设置为整个 UITableView 标题,并将保持可见的部分设置为第一个表格部分的标题视图。 因此,您可以使用单个 UITableView 来实现这一点,而无需使用 UIScrollView
【讨论】:
【参考方案4】:您正在寻找的是类似于 Game Center 碰巧与它的标题有关的东西和表格的边界。
首先,最简单的部分:伪造一个粘性视图。该“滚动表格时始终存在的视图”实现为节标题。通过表 1 中的部分数量,并实现-headerViewForSection:
,可以免费使视图与 tableview 无缝滚动(API 方面):
- (UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0,0,320,50)];
label.text = @"Info that was always present when scrolling the UITableView";
label.textAlignment = UITextAlignmentCenter;
label.backgroundColor = [UIColor colorWithRed:0.243 green:0.250 blue:0.253 alpha:1.000];
label.textColor = UIColor.whiteColor;
return label;
最后,困难的部分:KVO。当表格滚动时,我们必须保持标题相对于视图框架的顶部保持粘性,这意味着您可以 KVO contentOffset
,并使用由此产生的值变化来近似视图应该粘贴的框架用一点MIN()
魔法。假设您的标题是 44 像素高,下面的代码会计算适当的帧值:
CGPoint offset = [contentOffsetChange CGPointValue];
[self.tableView layoutSubviews];
self.tableView.tableHeaderView.frame = CGRectMake(0,MIN(0,offset.y),CGRectGetWidth(self.scrollView.frame),44);
如果上述方法不可行,SMHeadedList 实际上有一个相当出色但鲜为人知的示例,说明实现“双表视图”有多复杂。该实现具有允许“标题”表视图与“主”表视图一起滚动的额外好处。
对于未来的访问者,我已经实现了一个much simpler version,尽管它使用 Reactive Cocoa 实现了目标,并且有一点不同的结果。即便如此,我相信它可能是相关的。
【讨论】:
【参考方案5】:如果你把 UIView 分成顶部和底部怎么办。底部将是信息。
在viewDidLoad
中设置UITableView.tableHeaderView = topView
并在委托方法中返回 bottomView
作为 Section Header 以使其浮动:
(UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section
return bottomView;
【讨论】:
【参考方案6】:只需使用 UITableView 即可解决您的问题。不需要使用另一个滚动视图。
-
将您的视图设置为 UITableView 的标题视图。然后将您当前的视图添加到标题视图中。
完成
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
。 Tn检查滚动视图的内容偏移量,并设置当前视图的框架。
【讨论】:
以上是关于根据 UITableView 调整 UIScrollView 高度的主要内容,如果未能解决你的问题,请参考以下文章
如何根据ios 8中的内容动态调整UITableview Header高度
调整大小后 UITableView 混乱 | Objective-C
将 UITableView 大小调整为 iPhone 5/5s