iOS scrollView嵌套tableView的手势冲突解决方案

2018 年 11 月 3 日 CocoaChina

本公众号内容均为本号转发,已尽可能注明出处。因未能核实来源或转发内容图片有权利瑕疵的,请及时联系本号,本号会第一时间进行修改或删除。 QQ : 3442093904 


在平时项目中,我们经常会碰到类似UIScrollView嵌套UITableView的需求,虽然苹果并不建议这种做法,但是这样的需求在平时工作中还是很常见的。比如笔者公司项目之前用到的地方:


点击查看动态效果


可以看到最上面是一块轮播图组件,我也已经整理了一份轮播图组件在github上面,轮播图下面还有若干条其他的内容,而且这几块内容都是后台动态控制显示的,所以这里用UIScrollView设置顶部偏移量实现是很不方便的。最外层我肯定选择使用tableView分区管理来实现。而下面的横向分类页面肯定需要tableView去实现


这样的话问题就来了,先不说下面的横向分页如何实现,这个页面必定需要在一个tableView中嵌套多个不同的tableView,但是如果嵌套了其他的scrollView,就需要我们判断不同条件下让哪个scrollView响应滑动事件,因此这里我们需要解决的就是手势的冲突问题


最开始想到的是在滑动tableView时候根据偏移量设置scrollEnabled来控制两个tableView的响应,但是会有个问题就是当滚动到顶部时用户必须第二次滑动才可以显示出外层的tableView,这样就会造成一个卡顿的效果,所以这个方法是行不通的。

下面说一下我的解决思路:


这里就直接分为mainTableView和subTableView,设置mainTableView的联动手势UIGestureRecognizer


/**
 同时识别多个手势

 @param gestureRecognizer gestureRecognizer description
 @param otherGestureRecognizer otherGestureRecognizer description
 @return return value description
 */

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    return YES;
}


下面的分类pageView是直接使用了封装的page框架FSScrollContentView,在mainTableView的UIScrollViewDelegate方法内判断mainTableView的偏移量,当标题栏滚动到顶部的时候固定mainTableView的偏移量


- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGFloat bottomCellOffset = [_tableView rectForSection:1].origin.y - 64;
    if (scrollView.contentOffset.y >= bottomCellOffset) {
        scrollView.contentOffset = CGPointMake(0, bottomCellOffset);
        if (self.canScroll) {
            self.canScroll = NO;
            self.contentCell.cellCanScroll = YES;
        }
    }else{
        if (!self.canScroll) {//子视图没到顶部
            scrollView.contentOffset = CGPointMake(0, bottomCellOffset);
        }
    }
    self.tableView.showsVerticalScrollIndicator = _canScroll?YES:NO;
}


上面代码中的canScroll是定义的一个BOOL变量用来控制mainTableView的偏移量


此时,subTableView收到可以滚动的信号cellCanScroll,才开始响应滑动的手势,在subTableView的UIScrollViewDelegate方法内实现:


- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (!self.vcCanScroll) {
        scrollView.contentOffset = CGPointZero;
    }
    if (scrollView.contentOffset.y <= 0) {
        if (!self.fingerIsTouch) {
            return;
        }
        self.vcCanScroll = NO;
        scrollView.contentOffset = CGPointZero;
        [[NSNotificationCenter defaultCenter] postNotificationName:@"leaveTop" object:nil];//到顶通知父视图改变状态
    }
    self.tableView.showsVerticalScrollIndicator = _vcCanScroll?YES:NO;
}


其实到这里会发现主要是通过设置两个scrollView的偏移量来解决这个手势冲突的问题。因为代码已经表达的很清楚,不太擅长表达,这里只是大概描述一下使用场景。

具体的实现方式已经写成了一个demo,里面也有详细的注释,可以前去下载:FSScrollViewNestTableView


2017.6.21--应网友要求,demo添加了刷新逻辑


给大家看一下实现后的效果图:


点击查看动态效果


这里只是提供了一种解决方案,欢迎提出问题多多交流


作者:PURE蓝胖子

链接:https://www.jianshu.com/p/8bf6c2953da3


登录查看更多
0

相关内容

100+篇《自监督学习(Self-Supervised Learning)》论文最新合集
专知会员服务
161+阅读 · 2020年3月18日
PC微信逆向:两种姿势教你解密数据库文件
黑客技术与网络安全
16+阅读 · 2019年8月30日
PHP使用Redis实现订阅发布与批量发送短信
安全优佳
7+阅读 · 2019年5月5日
从webview到flutter:详解iOS中的Web开发
前端之巅
5+阅读 · 2019年3月24日
你头疼的ELK难题,本文几乎都解决了
DBAplus社群
8+阅读 · 2019年3月20日
这一次,彻底解决滚动穿透
IMWeb前端社区
34+阅读 · 2019年1月4日
已删除
AI科技评论
4+阅读 · 2018年8月12日
【干货】利用ENVI从航空影像中提取DEM
无人机
14+阅读 · 2018年1月8日
小米Note3 ‖ 国产首款支持人脸解锁手机
机械鸡
4+阅读 · 2017年9月12日
Monocular Plan View Networks for Autonomous Driving
Arxiv
6+阅读 · 2019年5月16日
Arxiv
5+阅读 · 2018年4月30日
Arxiv
6+阅读 · 2018年2月7日
Arxiv
3+阅读 · 2012年11月20日
VIP会员
相关VIP内容
100+篇《自监督学习(Self-Supervised Learning)》论文最新合集
专知会员服务
161+阅读 · 2020年3月18日
相关资讯
PC微信逆向:两种姿势教你解密数据库文件
黑客技术与网络安全
16+阅读 · 2019年8月30日
PHP使用Redis实现订阅发布与批量发送短信
安全优佳
7+阅读 · 2019年5月5日
从webview到flutter:详解iOS中的Web开发
前端之巅
5+阅读 · 2019年3月24日
你头疼的ELK难题,本文几乎都解决了
DBAplus社群
8+阅读 · 2019年3月20日
这一次,彻底解决滚动穿透
IMWeb前端社区
34+阅读 · 2019年1月4日
已删除
AI科技评论
4+阅读 · 2018年8月12日
【干货】利用ENVI从航空影像中提取DEM
无人机
14+阅读 · 2018年1月8日
小米Note3 ‖ 国产首款支持人脸解锁手机
机械鸡
4+阅读 · 2017年9月12日
相关论文
Top
微信扫码咨询专知VIP会员