作为iOS开发者,我们的苹果爸爸建议最好不要嵌套UIScrollView
。然而,设计师大大并不会关心我们的苹果爸爸~
关于UIScrolView
的嵌套问题,网上也有很多的解决办法,所以在阅读一些解决方案之后,有了一些自己的想法。
个人思路
主要用scrollView
的偏移量contentOffset
以及自带pan手势的滑动速度velocityInView:
使scrollView
做关联
注意
本文只是提供一种思路,因此仅用一个superScrollView
嵌套一个childScrollView
做示例,由本人从多标签生成的相应个数的scrollViews中提取。若有不足,感谢大家给予补充指正。
最终效果
界面搭建
首先,新建继承自UIScrollView
的BaseScrollView
,遵循协议UIGestureRecognizerDelegate
并打开scrollView
的多手势识别
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
创建对象 BaseScrollView *superScrollView
和UIScrollView *childScrollView
,并设置代理
即: headerView
与childScrollView
组成了superScrollView
的contentSize
此时的效果类似
显然,这并不是我们想要的效果。
添加关联判断
接下来需要我们在- (void)scrollViewDidScroll:(UIScrollView *)
代理方法中设置一些细节
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
UIScrollView *childScrollView = self.childScrollView;
UIScrollView *superScrollView = self.superScrollView;
///临界值
CGFloat topHeight = self.headerView.bounds.size.height;
///scrollView 滑动偏移量
CGFloat offsetY_super = superScrollView.contentOffset.y;
CGFloat offsetY_sub = childScrollView.contentOffset.y;
///pan手势 速度 ======> 判断滑动方向(下滑 -- y为正)
CGPoint velocity_sub = [childScrollView.panGestureRecognizer velocityInView:childScrollView];
CGPoint velocity_super = [superScrollView.panGestureRecognizer velocityInView:scrollView];
///滑动的手指放开时,速度变为 0
if (offsetY_sub > 0 && velocity_sub.y == 0 && velocity_super.y == 0) {
superScrollView.contentOffset = CGPointMake(0, topHeight);
}
///当速度为 0 时,不做以下代码处理
if (velocity_sub.y == 0 || velocity_super.y == 0) {
return;
}
///以下处理速度不为零的情况
if (offsetY_super >= 0 && offsetY_super < topHeight && velocity_sub.y < 0) {
// (a)手指上滑时,若superScrollView未超过临界值,则设置childScrollView的contentOffset
childScrollView.contentOffset = CGPointZero;
}
if (offsetY_sub > 0 && velocity_sub.y > 0) {
// (b)手指下滑时,若childScrollView未到顶点,则设置superScrollView的contentOffset
superScrollView.contentOffset = CGPointMake(0, topHeight);
}
else if (velocity_super.y > 0) {
// (c) 若childScrollView到顶点,固定childScrollView的contentOffset
childScrollView.contentOffset = CGPointZero;
}
}