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、源码地址

  • 2018-08-28 14:19:58

    php如何配置上传较大文件

     在php中判断上传文件的大小,但是文件一但过大,print_r($_FILES);的值就变为null了,有时候大家会遇到这么一个问题,上传小文件 时,PHP能正常获取到,但是文件一超过8M就变为空了,我在做项目的时候,就遇到这样的问题,我刚开始把最大上传文件值改为20M,在PHP.INI里 面。

  • 2018-08-28 15:09:50

    JAVA中MAP值保持顺序不变

    今天在进行JAVA开发过程中,因需要使用MAP来存放数据,同时希望MAP中KEY的顺序与放入顺序保持一致。 在使用HashMap之后,发现KEY的顺序是乱序的,每次打印还不太一样。上网查询资料之后发现:

  • 2018-09-03 13:57:27

    load average 的含义

    一般的进程需要消耗CPU、内存、磁盘I/O、网络I/O等资源,在这种情况下,平均负载就不是单独指的CPU使用情况。即内存、磁盘、网络等因素也可以影响系统的平均负载值。 在单核处理器中,平均负载值为1或者小于1的时候,系统处理进程会非常轻松,即负载很低。当达到3的时候,就会显得很忙,达到5或者8的时候就不能很好的处理进程了(其中5和8目前还是个争议的阈值,为了保守起见,建议选择低的)。

  • 2018-09-05 01:42:03

    git reset 回退以前某个版本及常用命令

    第一个命令只删除所有untracked的文件,如果文件已经被tracked, 修改过的文件不会被回退。而第二个命令把tracked的文件revert到前一个版本,对于untracked的文件(比如编译的临时文件)都不会被删除。