前言
在移动应用实际开发过程中,往往会有多个scrollview嵌套的界面需求,这种需求已经司空见惯,解决方案也多种多样,这里就介绍一下我认为最优的解决方案。
效果图:
Untitled.gif结构解读:
底层有一个UIScrollview子类,这里叫它mainScrollview;
mainScrollview下方嵌套了两个视图(通常这两个视图也用UIScrollview子类来处理,这里叫它moduleScrollview)。
毫无疑问,我们通常的做法是在mainScrollview的下方先嵌套一个横向滚动的UIScrollview子类,再在这个横向滚动的视图上嵌套n个子模块(像gif中的“图文详情”和“客户评分”两个子模块)。
这点我不做过多解释,结构的搭建争议不大,重点在交互上。
尝试过的思路:
有一种思路总结起来是,通过开启或者禁止mainScrollview和moduleScrollview的交互来达到何时响应某个scrollview的目的。在手指拖动的临界状态,通过大量的判断逻辑来主动控制某些scrollview的偏移量,进而达到“欺骗观众”的响应拖动状态。
缺点:逻辑复杂程度过大,容错处理很多,致命的缺陷是临界状态无法实现scrollview的减速效果(惯性效果),当然有的开发者会说利用核心动画能实现这一效果,但是,我认为这就太费周折了。
最佳方案:
首先我们来了解一个UIGestureRecognizerDelegate协议拟定的方法:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer;
这个方法的作用大致可以理解为是否允许手势穿透。在iOS开发中,相同的手势,响应者往往是最上层的视图,所以重写这个方法返回为YES就可以让下层的视图响应同样的手势。
值得注意的是,UIScrollview实现了这个协议的方法,所以,我们可以让子模块直接继承UIScrollview(或其子类),然后重写该方法。
如此一来,我们需要做的,仅仅是判断何时不让某个scrollview改变偏移量即可。
优点:实现简单,丝滑无卡顿
核心思想:让moduleScrollview 和mainScrollview 同时响应上拉或者下拉手势,只需判断何时不允许某个scrollview改变contentOffset
DEMO
DEMO见github地址:https://github.com/indulgeIn/YBMultistageScrollView
注意:DEMO中嵌套进了UIWebview,并简单做了逻辑处理方案,在iOS8系统以上的情况,还是建议大家将UIWebview更换为WKWebview,性能和兼容性的提升不容小觑。
网友评论
scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, scrollView.contentSize.height-scrollView.H);
}
if (self.levelListView.selectedIndex == 1 && _evaluateTableView.offsetType == OffsetTypeCenter) {
scrollView.contentOffset = CGPointMake(scrollView.contentOffset.x, scrollView.contentSize.height-scrollView.H);
}
这里设置外层scrollview的偏移的时候,怎么会循环的调用scrollview的scrollViewDidScroll方法,楼主可以帮忙看下吗
1、在最外层的界面的scrollViewDidScroll中,scrollView.contentSize.height-H-0.5这一块再多减去scrollView.contentInset.top
2、还是这个方法中遍历一下全部子Table,如果已经被拉到了屏幕中间,将其他子table的contentOffset全部置为Zero
if (idx != self.selectedIndex && self.offsetType != OffsetTypeMax) {
obj.contentOffset = CGPointZero;
}