1、为了展示嵌套效果,适配复杂布局内部采用了三个子ViewController:
FirstViewController 内部为TableView布局
SecondScrollViewController 内部为ScrollView布局
ThirdViewController 为CollectionView 布局
2、FirstViewController、SecondScrollViewController、ThirdViewController分别实现了NestedDelegate接口:
@protocol NestedDelegate <NSObject>
-(UIScrollView *)getNestedScrollView;
@end
3、ViewController中通过NestedDelegate
获取到子类的UIScrollView
,通过KVO监听UIScrollView->contentOffset
的变化:
[_currentNestedDelegate.getNestedScrollView addObserver:self forKeyPath:kObseverKeyContentOffset options:NSKeyValueObservingOptionNew context:nil];
(这里需要注意,切不可在ViewController中给_currentNestedDelegate.getNestedScrollView
设置滚动的代理,设置了会形成循环引用导致crash)
4、滚动处理的核心代码:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
//最大上滑距离
CGFloat maxOffset = _layoutHeaderViewHeight.constant;
CGFloat mainContentOffsetY = _mainScrollView.contentOffset.y;
if (scrollView == _mainScrollView) {
if (mainContentOffsetY > maxOffset) {
[_mainScrollView setContentOffset:CGPointMake(0, maxOffset)];
}else if(mainContentOffsetY < 0){
[_mainScrollView setContentOffset:CGPointMake(0, 0)];
}
}else if (scrollView == _currentNestedDelegate.getNestedScrollView){
UIScrollView *currentScrollView = _currentNestedDelegate.getNestedScrollView;
CGFloat currentOffsetY = currentScrollView.contentOffset.y;
//避免死循环
if (currentOffsetY == 0) {
return;
}
if(currentOffsetY < 0){
//下滑
if(mainContentOffsetY > 0){
//将子scrollview的滑动距离赋值给mainScrollView
[_mainScrollView setContentOffset:CGPointMake(0, mainContentOffsetY+currentOffsetY)];
//重置子scrollview的offset
[currentScrollView setContentOffset:CGPointMake(0, 0)];
}
}else if(currentOffsetY >0){
//上拉
if(mainContentOffsetY < maxOffset){
//将子scrollview的滑动距离赋值给mainScrollView
[_mainScrollView setContentOffset:CGPointMake(0, mainContentOffsetY+currentOffsetY)];
//重置子scrollview的offset
[currentScrollView setContentOffset:CGPointMake(0, 0)];
}
}
}
}
1、嵌套UITableView效果
2、嵌套UIScrollView效果
3、嵌套UICollectionView效果
1、源码地址