美文网首页iOS开发骚操作iOS分享世界为了更好的活着
UIScrollView嵌套滚动完美解决方案:仿淘宝、转转首页

UIScrollView嵌套滚动完美解决方案:仿淘宝、转转首页

作者: 开源者联盟 | 来源:发表于2019-11-27 09:41 被阅读0次

    前言

    随着APP承载的业务越来越多,一个页面显示的信息也越来越多,需要为不同的业务导流。主流的平台APP,诸如:淘宝、京东、转转、盒马、还有各类社交APP的个人主页,都需要在页面顶部展示核心业务数据,在底部分标签显示各个子业务列表数据。随着大屏手机的普及,如果只能通过点击顶部标签切换列表,对于使用场景最高的单手操作就很麻烦了。所以,为了用户更好的交互,需要支持子列表左右滚动切换的功能。这样就出现了UIScrollView嵌套滚动的场景了。既需要主列表上下滚动,也需要子列表左右滚动。

    现有的解决方案

    为了解决嵌套滚动的问题,现在网上已经有许多解决方案了。包括笔者我,也开源了一个JXPagingView库,目前已经有1100 stars,得到许多朋友的认可。
    主要支持以下特性:

    • 列表懒加载
    • 主列表、子列表下拉刷新
    • 悬浮位置调整
    • OC与Swift双版本
    • 封装度高,使用方便

    感兴趣的可以了解一下JXPagingView的原理

    基于现有的原理,有一个小问题:当用户在顶部header用力往上滑动的时候,当分类控制器滚动到顶部的时候,会突然停住,列表不会接着惯性继续滚动。大家可以打开【京东】APP,目前(版本号:8.3.4)首页的效果就是如此,大家可以体验一下,就明白我说的是什么意思了。

    如何才能像淘宝首页那样,可以让子列表接着滚动呢?直到看到了转转首页,通过上手体验之后,发现了一个全新的方案。PS:不知道转转APP做了什么操作,简单的逆向不起作用,视图层级都看不到。所以,这个方案都是靠自己猜测加实践折腾出来的。

    JXPagerSmoothView方案

    JXPagerSmoothView Github地址,点击立马体验

    效果预览

    image

    可以清楚的看到顶部pagerHeader用力往上滚动之后,下方列表会继续滚动的,而且滚动的速度、阻尼都是系统自带的。因为上下滚动的时候,就只是在操作一个列表,自然不会有手势冲突之类的问题,看了下面的原理解析就明白了。自定义的pagerHeader只是用一个简单的TableView作为示例,你可以用任何复杂的视图、UICollectionView等代替。

    此方案原理非常简单,没有复杂的手势处理,只需要处理好各种边界情况即可。

    情况一

    默认情况pagerHeaderContainerView被addSubview到当前的列表UIScrollView上面,pagerHeaderContainerView就是顶部pagerheader(核心业务视图区域)和pinHeader(悬浮分类控制器区域)的容器视图。这样子,列表上下滑动就只是在操作单个列表ScrollView,不会有滚动突然被中断的情况。视图层级如下:

    image

    情况二

    当列表在左右切换的时候、列表向上滚动到pinHeder悬浮的时候,pagerHeaderContainerView被addSubview到JXPagerSmoothView上面,也就是脱离了列表scrollView,达到固定在顶部的效果。视图层级如下:

    image

    总结:就是在不断切换pagerHeaderContainerView的父视图,达到淘宝、转转首页的效果。是不是原理很简单?当然使用的代码也很简单!

    使用示例

    1、初始化JXPagerSmoothView

        self.pager = [[JXPagerSmoothView alloc] initWithDataSource:self];
        [self.view addSubview:self.pager];
    

    2、初始化pagerHeaderpinHeader

        self.categoryView = [[JXCategoryTitleView alloc] init];
        self.categoryView.titles = @[@"能力", @"爱好", @"队友"];
        self.categoryView.contentScrollViewClickTransitionAnimationEnabled = NO;
    
        self.pagerHeader = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"lufei.jpg"]];
    

    3、实现JXPagerSmoothViewDataSource代理方法

    - (CGFloat)heightForPagerHeaderInPagerView:(JXPagerSmoothView *)pagerView {
        return 300;
    }
    
    - (UIView *)viewForPagerHeaderInPagerView:(JXPagerSmoothView *)pagerView {
        return self.pagerHeader;
    }
    
    - (CGFloat)heightForPinHeaderInPagerView:(JXPagerSmoothView *)pagerView {
        return 50;
    }
    
    - (UIView *)viewForPinHeaderInPagerView:(JXPagerSmoothView *)pagerView {
        return self.categoryView;
    }
    
    - (NSInteger)numberOfListsInPagerView:(JXPagerSmoothView *)pagerView {
        return self.categoryView.titles.count;
    }
    
    - (id<JXPagerSmoothViewListViewDelegate>)pagerView:(JXPagerSmoothView *)pagerView initListAtIndex:(NSInteger)index {
        SmoothListViewController *listVC = [[SmoothListViewController alloc] init];
        return listVC;
    }
    

    4、列表实现JXPagerSmoothViewListViewDelegate代理方法

    SmoothListViewController类实现JXPagerSmoothViewListViewDelegate代理方法

    - (UIScrollView *)listScrollView {
        return self.tableView;
    }
    
    - (UIView *)listView {
        return self.view;
    }
    

    使用注意事项

    通过示例代码可以看到整个逻辑简单、清晰,和使用UITableView一样,只需要实现对应的代理方法即可,根本不需要操心页面的交互逻辑。真正的做到了高内聚低耦合、职责分离等原则。

    但是有几个点需要注意:

    • 不要自己设置列表滚动视图的contentInset属性,内部通过设置contentInset来添加pagerHeaderContainerView;
    • 当顶部pagerHeader是一个UIScrollView及其子类时,需要让contentSize.height=pagerHeader的高度,即不能让其能够滚动,详情可以参考OC示例demo的SmoothCustomPagerHeaderViewController类;
    • 请仔细辨别JXPagerViewJXPagerSmoothView的区别,并选择适合自己需求的类;
    • JXPagerSmoothView在1.2.1及以上版本才有,请使用最新版本;
    • Swift版本是JXPagingSmoothView;

    JXPagerSmoothView Github地址

    JXPagerSmoothView Github地址,点击立马体验

    总结

    JXPagerSmoothView的实现文件只有300行代码左右,需要深入研究的朋友,相信花点功夫就能看懂。这样子以后业务上面有任何特殊要求时,都可以自己实现。只要掌握了原理,就不怕需求的变化。

    有任何建议或疑问,可以留言、提Issues,我都会第一时间回复你!

    感谢你的阅读,喜欢就点个赞吧💖

    相关文章

      网友评论

        本文标题:UIScrollView嵌套滚动完美解决方案:仿淘宝、转转首页

        本文链接:https://www.haomeiwen.com/subject/srguwctx.html