在滚动之前实现UITableView移动的效果

yon*_*ano 6 scroll objective-c uitableview

描述

如果您在iOS或Android上使用Spotify应用程序(我在iOS上开发),您会注意到如果选择播放列表,并将UITableView与歌曲一起向上拖动,则会发生以下情况:

该表不会滚动,它只是以与滚动相同的速度向上移动,并且其上方的图像比表格移动得慢,从而产生视差滚动效果.然而,一旦tableview到达视图的顶部,它就像普通的滚动tableview一样.

我试图通过几种不同的方式实现这种效果,这对我不起作用.

以下是此效果的视频:https://www.dropbox.com/s/n7npk4lrzmag0sn/IMG_9331.MOV

我尝试了什么

我希望UITableView和它上面的UIScrollView在用户滚动任何一个时向上移动,所以我使用了

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
Run Code Online (Sandbox Code Playgroud)

并根据滚动的方向,我改变了tableview的框架位置和它上面的UIScrollView.

这种方法的问题在于tableview反弹,这会破坏效果.

为了摆脱弹跳,我尝试了以下方法:

_userTableView.bounces = NO;
Run Code Online (Sandbox Code Playgroud)

但是,现在因为tableview不会滚动,所以从不调用scrollViewDidScroll.

我尝试的另一件事是继承UITableView,并覆盖

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
Run Code Online (Sandbox Code Playgroud)

用于检测tableview上的滚动手势的hitTest方法,其问题是:

  • 只传递了1个CGPoint - 无法知道UITableView是否被触摸或滚动.
  • 由于滚动被禁用,我无法使用self.decelerating来检查tableview是否只是滚动 - tableview永远不会减速
  • 当桌子向上移动时使桌子减速,并且在到达顶部后以相同的动量继续滚动将是非常具有挑战性的; 在Spotify应用程序中,用户可以以足够高的速度拖动表格,使表格视图移动到视图的顶部并继续滚动,所有这些都在一个动作中.

tableview的大小应该会增加,以容纳更多添加到视图中的单元格(无需滚动),因为它向上移动视图,或者它应该以与视图相同的大小开始.在它到达顶部之后,它应该像普通的桌面视图一样开始滚动 - 在向上移动之后具有相同的动量.

关于如何解决这个问题的任何建议?

非常感谢你.

Joh*_*pia 2

对于您所显示的效果,我认为tableHeaderView将视差内容作为子视图就足够了。

-scrollViewDidScroll:(或 KVO for contentOffset)中,您将center视差子视图的 设定为 的可见边界的中心tableHeaderView。您还可以通过乘以一个系数来调整内容“粘”在中心的程度。

CGRect tableViewHeaderVisibleBounds = tableViewHeader.bounds;
tableViewHeaderVisibleBounds.origin.y = MAX(0, MIN(CGRectGetHeight(tableViewHeader.bounds), tableView.contentOffset.y));
tableViewHeaderVisibleBounds.size.height -= tableViewHeaderVisibleBounds.origin.y;

CGFloat factor = 1.8f; // less than 0.5:stick to top // greater than 0.5:stick to bottom 
parallaxContentView.center = (CGPoint){
    .x = parallaxContentView.center.x,
    .y = (CGRectGetMinY(tableViewHeaderVisibleBounds)
         + (CGRectGetHeight(tableViewHeaderVisibleBounds) * factor))
};
Run Code Online (Sandbox Code Playgroud)

我在脑海中编写了这个代码,因此只需进行必要的调整,但我希望您能了解基本的想法。