根据 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

UITableView 单元格在调整大小后不响应输入

以编程方式调整 Storyboard 中 UITableView 的 y 值

动态调整UITableView的大小,该大小将显示为不可滚动的内容列表