iOS ScrollView嵌套tableView联动滚动的思路与最佳实践

前言

随着业务的发展,页面的复杂度越来越高,嵌套滚动视图的方式也越来越受设计师们的青睐,在各大电商App十分常见。如下Demo图:

但是这样的交互官方并不推荐,而且对开发来说确是不那么友好,需要处理滚动手势的冲突,页面的多层级嵌套都给开发带来了一定程度的麻烦。接下里我聊聊我们的实现思路。

思路和过程

对应这种页面结构应该毫无疑问是最底层是一个纵向滚动的scrollView,它的页面上面放一个固定高度的header,紧接着下面一个支持横向滚动切换的容器scrollView,容器上面才是各个页面具体的tableView,如下图:

思路一

最先想到的是,既然是滚动视图那么我们是否可以通过滚动视图的可滚动属性来做呢,在初始时把最上层具体业务的tableView禁止滚动,那么根据事件响应链,滚动事件事件会由底层的ScrollView接收并处理,在到达最大偏移量之后,禁用底层的ScrollView滚动,同时开启上层的tableView,使得上层可以滑动,想起来是有一定可行性的,可惜,事实现实是残酷的,效果如下:

这样会导致当偏移量到达临界值时,由于设置了scrollEnable属性和最大偏移量,此次滚动手势会被截断,需要再次拖拽才能继续滚动,显然,这样的效果是无法接受的。

思路二

这是同事提供的思路,在做这个时和同事有过讨论,他们之前有这样的交互页面,使用的是自定义手势,但由于UIScrollView是有弹性效果的,一般的滑动手势做不到这一点的,所以需要引入UIDynamic模拟力场,实现阻尼效果。想了一下,虽然有一定的可行性,但是为了一个联动滑动,要做这么多的事情,感觉比较繁琐,而且自定义手势做的模拟弹性效果可能和原生ScrollView的效果还是有一定的差距,所以选择放弃。

思路三

回到我们思路一,除了边界位置会阻断联动滚动外,其他效果还是可以的,那么能不能通过手段解决这个问题呢?既然能写到了这里,那么毫无疑问,肯定是可以的。通过手势穿透,即让一个滑动手势既作用于底层的ScrollView又能作用于上层的业务tableView,同时控制他们的滚动即可达成目的。通过让底层的scrollView实现一个手势识别的协议,同时响应滚动事件:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
 return true
 }

根据官方文档描述:

Asks the delegate if two gesture recognizers should be allowed to recognize gestures simultaneously.

表达的意思是询问委托是否允许两个手势识别器同时识别手势,那么我们实现这个协议,”穿透“手势,分别在底层容器和上层业务中实现滚动视图的代理方法func scrollViewDidScroll(_ scrollView: UIScrollView),分别控制他们的可滚动状态和偏移量则能实现目的。部分实现如下:

底层容器ScrollView:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
  headerView.isHidden = scrollView.contentOffset.y >= maxOffset ? true : false
  if !superCanScroll {
   scrollView.contentOffset.y = maxOffset
   currentVC.childCanScroll = true
  } else {
   if scrollView.contentOffset.y >= maxOffset {
    scrollView.contentOffset.y = maxOffset
    superCanScroll = false
    currentVC.childCanScroll = true
   }
  }
 }

上层业务tableView:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
  if !childCanScroll {
   scrollView.contentOffset.y = 0
  } else {
   if scrollView.contentOffset.y <= 0 {
    childCanScroll = false
    superCanScrollBlock?(true)
   }
  }
 }

通过底层ScrollView是否达到最大偏移量控制header的显示隐藏和对应的偏移量及可滚动状态,在业务tableView使用回调将ScrollView的可滚动状态回调达到状态同步。总体来说还是比较清晰,更多细节请看QFMultipleScrollView

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。

(0)

相关推荐

  • ios scrollview嵌套tableview同向滑动的示例

    我讨论的问题是嵌套同向滑动,能避免尽量避免.最好用一个tableview实现.一个tableview不够用了再嵌套,适用复杂场景. 首先我说下不适用的,免得大家浪费时间. 1.不适用上下拉刷新加载更多的页面. 2.不适用点击cell获取点击事件的页面,可以加入button点击获取事件. 官方文档说尽量不要进行两个竖直或两个水平方向滑动的视图嵌套.因为这个时候机器不知道用户要让哪个滑动,但在我们这个神奇的国度,项目中经常出现这样的需求,产品经理总爱这样做,andriod那边是比较容易实现的,ios

  • iOS中UIScrollView嵌套UITableView的实践教程

    前言 最近因为工作项目中需要用到UIScrollView嵌套UItableView嵌套交互问题,顺便网上搜了下的demo,发现实现的效果并不是很理想,滑动偶尔会有延迟现象,所以自己想了个办法,顺便把自己实现写了个demo分享出来,一起来看看吧. 实现过程 最底部放置的为一个UIScrollView,设置ScrollView的contentSize属性,使可以发生横向滚动,同时隐藏横向滚动条,设置代理为当前控制器本身.然后,在最底部的UIScrollView上放置2个UITableView,因为只

  • iOS ScrollView嵌套tableView联动滚动的思路与最佳实践

    前言 随着业务的发展,页面的复杂度越来越高,嵌套滚动视图的方式也越来越受设计师们的青睐,在各大电商App十分常见.如下Demo图: 但是这样的交互官方并不推荐,而且对开发来说确是不那么友好,需要处理滚动手势的冲突,页面的多层级嵌套都给开发带来了一定程度的麻烦.接下里我聊聊我们的实现思路. 思路和过程 对应这种页面结构应该毫无疑问是最底层是一个纵向滚动的scrollView,它的页面上面放一个固定高度的header,紧接着下面一个支持横向滚动切换的容器scrollView,容器上面才是各个页面具体

  • IOS实现左右两个TableView联动效果

    一.先来看看要实现的效果图 二.小解析,可以先看看后面的! 三.实现 tableView联动 主要分两种状况 1.点击 左侧 cell 让右侧 tableView 滚到对应位置 2.滑动 右侧 tableView 让左侧 tableView 滚到对应位置 1.先实现简单的:点击 左侧 cell 让右侧 tableView 滚到对应位置 //MARK: - 点击 cell 的代理方法 - (void)tableView:(UITableView *)tableView didSelectRowAt

  • iOS开发中TableView类似QQ分组的折叠与展开效果

    类似QQ分组的样子,实现tableView的折叠与展开.其实要做这个效果我先想到的是在tableView中再嵌套多个tableView,这个想法实现起来就有点难了. 所以还是换个思路,把tableView的HeaderView用上了.给headerView加上手势,轻松解决折叠展开的问题. 直接上代码吧. @property (nonatomic, strong) UITableView *myTableView; @property (nonatomic, strong) NSMutableA

  • iOS模拟中奖名单循环滚动效果

    本文实例为大家分享了iOS模拟中奖名单循环滚动效果的具体代码,供大家参考,具体内容如下 1.动态效果图: 2.思路: (1)控件:一个父View,依次添加两个tableVew,使其上下紧挨着,高度均等于所有cell的总高度,且加载相同的的数据,父视图的clipsToBounds属性一定要设置为true (2)滚动:使用计时器,调整时间及滚动大小,使展示平滑 (3)循环算法:当A列表滚动出界面时,就把它添加在B列表的下面,B列表滚动出界面时,就把它添加在A列表的下面,形成循环效果 3.Swift版

  • 在android中ScrollView嵌套ScrollView解决方案

    大家好,众所周知,android里两个相同方向的ScrollView是不能嵌套的,那要是有这样的需求怎么办?(这个需求一般都是不懂android的人提出来的) 难道就真的不能嵌套吗?当然可以,只要你再写一个ScrollView,在里面做点脚,它就支持嵌套了. 目前做的这个只支持两个ScrollView嵌套,两个以上还有待改进,能套两个就已经能满足很多需求了,呵呵,另外现在只做了纵向scrollview的支持,横向的还没来的急做哦. 效果截图:  先上核心代码吧.代码里头我加了注释,方便大家阅读

  • Android 中ScrollView嵌套GridView,ListView的实例

    Android 中ScrollView嵌套GridView,ListView的实例 在Android开发中,经常有一些UI需要进行固定style的动态布局,然而由于现在的UI都喜欢把一个界面拉的很长,所以我们很多情况下需要使用ScrollView来嵌套列表控件来实现UI.这样就导致了很多不顺心的问题. 问题一:列表控件显示不完全 原因是嵌套情况下,ScrollView不能正确的计算列表控件的高度. 有两种解决方案 方案一 在适配器赋值完成后代码动态计算列表的高度.这里贴出ListView的计算代

  • iOS使用UICollectionView实现横向滚动照片效果

    本文实例为大家分享了iOS使用UICollectionView实现横向滚动展示照片的具体代码,供大家参考,具体内容如下 这是Demo链接 效果图 思路 1. 界面搭建 界面的搭建十分简单,采用UICollectionView和自定义cell进行搭建即可. // ViewController.m // 下面使用到的宏和全局变量 #define ScreenW [UIScreen mainScreen].bounds.size.width #define ScreenH [UIScreen main

  • 微信小程序scroll-view实现左右联动效果

    微信小程序利用scroll-view实现左右联动,供大家参考,具体内容如下 点击左边的按钮时,右边可以跳动到指定的位置 首先要注意使用scroll-view竖屏滚动,需要给scroll-view固定高度 其次在点击时,需要给需要滚动的scroll-view加上scroll-into-view,其值应该是子元素的id,且id不能以数字 开头 滚动右边,左边菜单跳到相应的位置 其实现的思想是,在右边滚动屏滚动时,得到滚动的距离.将右边滚动屏中各模块到达顶部的距离计算出来放到一个数组中.第一个模块的滚

  • 微信小程序scroll-view实现左右联动

    本文实例为大家分享了微信小程序scroll-view实现左右联动的具体代码,供大家参考,具体内容如下 需求:项目中做了一个选择城市的需求,要求全国所有的省市区都按照中文首字母分类并排序,左侧的城市列表和右侧的字母列表实现双向联动. 第一步:根据腾讯提供的javascript SDK提供的接口,获取所有的省市区,并将省市区按照首字母进行分类排序. let _this = this; _this.mapCtx = wx.createMapContext("myMap"); // 实例化AP

随机推荐