自定义多tab表联动滑动

用UICollectionView实现多表联调滑动。

引言

最近接了一个需求,要实现多表联动滑动的效果,同时需要支持菜单栏置顶,下拉刷新功能。特此记录遇到的坑。

先看实现效果。

方案一

实现多表滑动的时候,首先想到的是用系统的UIPageViewController,可以方便的为我们管理controller的生命周期。但这个类已被高度封装,无法获取内部scrollview的属性和scroll的偏移值(也可以获取,就是有点麻烦),同时子controller出现的时机也难以把握。更重要的是 有一些坑,比如快速滑动 与 快速点击的时候,有时候会崩溃。所以这个方案不可行。

方案二

使用UICollectionView,可以获取子view的滑动值,但必须自己控制生命周期。即封装成一个UIPagecontroller。故采用这种方案。

实现

1、用UICollectionView实现左右滑动,设置cell的大小为当前屏幕的大小,这样每切换滑动一次可以切换一个cell,即

itemSize = self.view.size

2、为了将多个子列表解耦,必须为每个列表单独创建一个VC。通过addChildController、removeController的方式,显示VC对应的View。
这个有两个坑

1、复用UICollectionViewCell的时候 需要清除之前的VC 和 VIew。对应的VC可以通过nextreponder 的方式寻找。

2、当UICollectionView滑动停止的时候,需要清除当前不在显示区域的VC 和 view。保证只有一个VC和对应的view显示。

3、为了显示顶部的悬浮菜单栏TopView,并且不跟随UICollectionView左右滑动,故设置跟UICollectionView同级。

4、TopView会盖住子列表的部分内容,还需要设置子列表的contentInset.top = TopView.frame.height

完成以上四步,框架基本搭建完成,下面将逐一解决遇到的问题。

###问题###

可以在TopView上添加一个监听上下滑动的UIPanGesture手势。TopView有可能会展示左右滑动的banner,所以在触发手势的时候,需要判断是否是上下滑动手势。如果是则联动子列表一起滑动

override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    if gestureRecognizer == self.panGesutre {
        let point = self.panGesutre.translation(in: self)
        if abs(point.y) > abs(point.x) {
            return true
        }
        return false
    }
    return true
}

通常情况下在我们会在viewdidload调用 mjheader.beginRefresh()。该方法会使得当前列表偏移 cotentInset.top + 刷新控件.height。并产生下拉动画。该动画会联动TopView一起滑动。,如果第一次显示页面时,不是在原先设定的初始位置,此动画有可能导致TopView无法固定悬浮。目前也只能暂时规避,不调用mj_header.beginRefresh(),自定义刷新。

    reloadData()
    tableView.layoutIfNeeded() //进行强制刷新

代码

github下载

参考

YNPageViewController

显示 Gitment 评论
0%