tableView嵌套tableView的功能实现

前言

以前公司做过一个tableView嵌套tableView滚动的功能实现。今天特意重新的整理了一下这个功能的实现。

功能需求说明:

  • 顶部是一个banner图片
  • 侧边栏
  • 内容tableView
    具体的实现效果图如下:
    功能需求.gif

    这个功能一开始的实现的方式是采用的ScrollView嵌套TableView实现的。又重新的写了一下这个功能模块。这次采用的是tableView嵌套tableView实现的此功能。
    特别说明
    文章中实现的功能和此功能略有差异,但实现的思路是一样的

具体实现

在说明实现方法之前先上一下现在的效果图

效果图.gif

功能实现部分
1.创建一个主控制器MainController

  • 给当前视图添加一个是否可以滚动的参数canScroll。关于这个参数的使用后面再做说明
  • 控制器创建一个tableView
  • 给tableView实现相关的代理方法
  • tableViewCell的数量为1
  • 给tableView设置headerView
  • tableView设置SectionHeaderView。这个地方的headerView是为了满足多个标题而准备的。如果不需要这个标题只需要一个banner的话完全可以使用ScrollView+tableView来实现这个功能就可以了。
    特别注意:
    关于Cell高度的设置应该是一个屏幕的高度 - SectionHeaderView的高度。或者说是你当前tableView的高度 -SectionHeaderView的高度。当前tableView的ContentSize的大小应该是tableHeaderView的高度+tableView的高度 - SectionHeaderView的高度

2.自定义tableViewCell
我这里要实现左右滑动切换tableView所以用到了一个ScrollView。如果没有多个标题的需求的话是不需要这个ScrollView的

  • 创建一个ScrollView
  • ScrollView的高度值和你当前Cell的高度一致,宽度根据你的标题个数设置。我这里是两个标题所以我的宽度应该是屏幕宽*2
  • 创建两个tableView添加到ScrollView上面去。tableView的高度和ScrollView高度一致。宽度是屏幕宽

至此页面的样式写完了。
这个时候运行程序的时候会发现上面的tableView和下面的tableView的滚动存在冲突

3.解决tableView嵌套滚动冲突的问题

  • 自定义一个新的tableView
  • tableView实现UIGestureRecognizerDelegate
  • tableView实现UIGestureRecognizerDelegate中的这个方法gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool
  • 判断方法中gestureRecognizerotherGestureRecognizer是否为UIPanGestureRecognizer 是的话返回true,不是的话返回false。这个地方其实也可以直接返回True
    代码如下
import UIKit

class BaseTableView: UITableView , UIGestureRecognizerDelegate {

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return gestureRecognizer.isKind(of: UIPanGestureRecognizer.self) && otherGestureRecognizer.isKind(of: UIPanGestureRecognizer.self)
    }
}

4.实现丝滑滚动

我相信很多第一次接触这个功能的时候,很多人想到的方法是利用tableView的ScrollEnable属性来解决滚动冲突的问题千万不要这样做。千万不要这样做。千万不要这样做。一旦你这么做了的话,后果就是当你发现要切换两个视图的ScrollEnable属性的时候会出现明显的卡顿情况。
正确的做法应该是设置tableView的contentOffset的值

  • 设置MainControllerscrollViewDidScroll方法,当滚动高度大于等于tableHeaderView高度的时候设置tableView的contentOffsetY的高度一直为tableHeaderView的高度。一开始设置的呢个canScroll属性就起作用了。具体代码如下:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
        //如果高度大于等于tableHeaderView的高度的时候
        if scrollView.contentOffset.y >=  HEADER_HEIGHT{
            //设置ContentOffsetY的高度为tableHeaderView的高度
            scrollView.contentOffset = CGPoint(x: 0, y: HEADER_HEIGHT)
            if self.canScroll {
                self.canScroll = false//设置是否可以滚动的参数为false
                //发送通知给子tableView。设置子tableView的可滚动属性为true
                NotificationCenter.default.post(name: NSNotification.Name(rawValue: "ChilderNotice"), object: nil)
            }
        }else{
            if !self.canScroll {
                scrollView.contentOffset = CGPoint(x: 0, y: HEADER_HEIGHT)
            }
        }
    }
  • 设置子tableView的滚动事件。具体代码如下:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
        //开始的时候子视图是无法滚动的  canScroll属性为false
        if !self.canScroll{
            scrollView.contentOffset = CGPoint.zero
        }
        //如果子视图的滚动高度小于等于0证明子视图滚动到了头部
        if scrollView.contentOffset.y <= 0 {
            self.canScroll = false
            //给主视图的tableView发送改变是否可以滚动的状态。让主视图的tbaleView可以滚动
            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "mainNotice"), object: nil)
        }
    }

5.完整的代码下载地址

完整代码下载地址

6.感谢a1203302261提供的代码优化

效果图1.png
效果图2.png
效果图3.png

百度网盘:9vxh
github
此优化由用户@a1203302261提供。在此只做总结方便下载

你可能感兴趣的:(tableView嵌套tableView的功能实现)