UIScrollView嵌套UIScrollView、UITableView、UICollectionView的滚动处理

2021-01-12 22:19:08

参考链接 UIScrollView嵌套UIScrollView、UITableView、UICollectionView的滚动处理

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效果


嵌套UITableView效果.gif

2、嵌套UIScrollView效果


嵌套UIScrollView效果.gif

3、嵌套UICollectionView效果


“嵌套UICollectionView效果.gif



1、源码地址

  • 2020-12-22 12:02:41

    ios开发优秀的开源框架,demo集合

    期待大家和我们一起共同维护,同时也期望大家随时能提出宝贵的意见(直接提交issues即可)。请广大网友只按照目录结构(即使目录结构有问题)添加三方库,并提交pull request。目录问题大家提出issues后楼主会及时更改的。

  • 2020-12-27 20:36:10

    音频播放AudioTrack之入门篇

    AudioTrack是管理和播放单一音频资源的类。AudioTrack仅仅能播放已经解码的PCM流,用于PCM音频流的回放。