UIScrollView中的UIScrollView,如何在两者之间滚动时保持平滑过渡

我有以下布局(见下文),对于大多数情况下,工作得很好。 用户可以在蓝色的UIScrollView进行滚动(对于所有的意图和目的都是一个UITableView ,但这个问题概括了这个),然后当他们到达这个滚动视图的末尾时,他们可以再次开始滚动(他们有取消他们的手指,并再次,因为内部滚动视图rubberbands否则),“超级”滚动视图开始滚动,显示其余的图像。

这是整个(他们必须把他们的手指,再次,因为内部滚动视图rubberbands否则) ,我不想要的。 理想情况下,一旦包含的UIScrollView到达其内容的末尾,我想让超级视图直接滚动,以便内部滚动视图不会橡皮筋。

用户滚动时也一样; 当红色滚动视图到达其内容的顶部时,我希望内部蓝色滚动视图开始向上滚动,而不是顶部的红色滚动视图橡皮筋。

屏幕布局; UIScrollView中的UIScrollView + UIImageView

任何想法如何? 我能够确定滚动视图何时到达其内容的末尾,但我不知道如何应用这些知识来达到我所追求的效果。 谢谢。

 // Inner (blue) scroll view bounds checking if (scrollView.contentOffset.y + scrollView.frame.size.height > scrollView.contentSize.height) { ... } // Outer (red) scroll view bounds checking if (scrollView.contentOffset.y < 0) { ... } 

是啊。 我有一个漂亮的把戏给你。

而不是让你的红色轮廓视图scrollview使它成为一个正常的UIView填充屏幕。 在该视图中,展示了您的滚动视图(表格视图)和图像视图,如图所示。

在所有其他滚动视图和图像视图之上放置一个滚动视图,以填充根视图的边界(即也填充屏幕)。 将此视图的内容大小设置为要滚动的所有视图的总内容高度。 换句话说,坐在所有其他视图之上的是一个不可见的scrollview,它的内容大小高度是内部滚动视图(tableview)内容大小高度+图像视图大小高度。

层次结构应该是这样的:

在这里输入图像说明

然后,这个滚动视图,你已经做出了真正的高内容大小,使其代表作为您的视图控制器。 实现scrollViewDidScroll ,我们将工作一些魔术。

Scrollviews基本上通过调整dynamic和东西的时髦公式的界限来源滚动。 所以在我们的scrollviewDidScroll方法中,我们将简单地调整底层视图的界限:

 -(void)scrollViewDidScroll:(UIScrollView *)scrollView{ //the scroll view underneath (in the container view) will have a max content offset equal to the content height //but minus the bounds height CGFloat maxYOffsetForUnderScrollView = self.underScrollView.contentSize.height - self.underScrollView.bounds.size.height; CGRect scrolledBoundsForContainerView = self.view.bounds; if (scrollView.contentOffset.y <= maxYOffsetForUnderScrollView) { //in this scenario we are still within the content for the underScrollView //so we make sure the container view is scrolled to the top and set the offset for the contained scrollview self.containerView.bounds = scrolledBoundsForContainerView; self.underScrollview.contentOffset = scrollView.contentOffset; return; } //in this scenario we have scrolled throug the entirety of the contained scrollview //set its offset to the max and change the bounds of the container view to scroll everything else. self.underScrollView.contentOffset = CGPointMake(0, maxYOffsetForUnderScrollView); scrolledBoundsForContainerView.origin.y = scrollView.contentOffset.y - maxYOffsetForUnderScrollView; self.containerView.bounds = scrolledBoundsForContainerView; } 

你会发现scrollViewDidScroll被调用的每一帧animation,包含的视图的虚假滚动看起来很自然。

可是等等! 我听到你说。 现在顶部的滚动视图拦截所有的触摸,并且它下面的视图也需要被触摸。 我也有一个有趣的解决scheme。

设置顶部的滚动视图在屏幕外某处(即将其框架设置为离开屏幕,但尺寸仍然相同),然后在viewDidLoad方法中将scrollview的panGestureRecogniser添加到主视图。 这意味着你可以在屏幕上看到所有的自然滚动animation和东西。 包含的滚动视图现在可能会变得犹豫,因为它的平移手势识别器也会被调用(它们对UIEvent处理的工作方式不同),因此您需要将其删除。

 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self.view addGestureRecognizer:self.scrollview.panGestureRecognizer]; [self.underScrollview removeGestureRecognizer:self.underScrollView.panGestureRecognizer]; //further code to set up content sizes and stuff } 

我很开心,所以inheritance人链接到github上的示例项目: https : //github.com/joelparsons/multipleScrollers

编辑:

为了显示顶部滚动视图的滚动条,不pipe你把它放在哪里,你都可以将scrollIndicatorInsets设置为一个插入,如下所示:

 CGPoint scrollviewOrigin = self.scrollview.frame.origin; self.scrollview.scrollIndicatorInsets = UIEdgeInsetsMake(-scrollviewOrigin.y,0,scrollviewOrigin.y,scrollviewOrigin.x); 

*注意,滚动视图仍然必须是正确的高度,但我相信你明白了。

然后,如果要在滚动视图的可见边界之外绘制条,则必须将剪辑closures

 self.scrollview.clipsToBounds = NO;