使用UIPageViewController构建通顶的分页视图

作为一名iOS开发者,大家一定都接触和使用过很多分页视图,也一定用过许多优秀的第三方分页视图组件例如JXPagingView等,但是笔者在实际的开发中遇到了全新的需求,如下图所示:

contentView要求要越过tab栏,那么市面上已有的pageView组件便都不能满足这个要求了。 本文将介绍一种contentView越过tab栏的pageView实现思路。

为了能够更快的实现需求,本人决定不使用类似JXPagingView的实现方法,以极简的方式快速实现需求。同时为了方便与同事间的协作,最终选择了UIPageViewController作为底层的滚动视图来承接各个tab下的uiviewcontroller。

有关UIPageViewController的介绍请查阅:blog.csdn.net/HDFQQ188816...

接下来我们直接看如何实现上述效果:

php 复制代码
//1.创建一个uiviewcontroller的实例,并实现相关协议
class BaseViewController:UIViewController,UIPageViewControllerDelegate,UIPageViewControllerDataSource{

//定义UIPageViewController的实例  
    private var pageViewController:UIPageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)

//用于保存contentViewControllers
    private var controllers = [UIViewController]()
    
//获取索引
    private var currentIndex:Int = 0;
    
//定义一个tab视图
    private let categoryView:FindBaseCategoryView = FindBaseCategoryView.init(frame: CGRect.init(x: 0, y: 94, width: screenWidth, height: FitX(value: 51.5)))

//这里定义了一个数据源,当数据源刷新时,初始化pageViewController
    private var titles:[String] = []{
        didSet{
            pageViewController.view.frame = CGRect(x: 0, y: 0, width: (UIScreen.main.bounds.width), height: (UIScreen.main.bounds.height))

            pageViewController.view.backgroundColor = .clear
            pageViewController.delegate = self
            pageViewController.dataSource = self
            pageViewController.view.backgroundColor = .white
            addChild(pageViewController)
            view.addSubview(pageViewController.view)
            pageViewController.didMove(toParent: self)
            view.gestureRecognizers = pageViewController.gestureRecognizers
            pageViewController.setViewControllers([controllers[0]], direction: .forward, animated: false)
            
            self.view.addSubview(categoryView)
            self.categoryView.titles = self.titles
        }

    }
}

下面实现UIPageViewController滑动手势的代理方法,每次代理事件结束就刷新数据源

swift 复制代码
//往左边滑动翻页会走此方法(类似pop回来)

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?{
        let index = self.controllers.firstIndex(of: viewController)
        if (index == 0) || (index == NSNotFound) {
            return nil
        }
        //守护,防止空值在解包时崩溃
        guard let index1 = index else {
            return nil
        }
        return controllers[index1 - 1]
    }
    
   //往左边滑动翻页会走此方法(类似push下去)
   func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController?{
        //获取当前控制器索引
        let index = self.controllers.firstIndex(of: viewController)
        if index == NSNotFound {
            return nil
        }
        if (index == self.controllers.count-1) {
            //防止越界,必须要设置
            return nil
        }
        //守护,防止空值在解包时崩溃
        guard let index1 = index else {
            return nil
        }
        return controllers[index1+1]
    }

    
   func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
        let controller = pageViewController.viewControllers?[0] ?? UIViewController.init()
        let index = controllers.firstIndex(of: controller)
        categoryView.currentIndex = index
        currentIndex = index ?? 0
        self.setNavStatus()
    }

此外,当点击上面的tab切换page的时候,要控制pageViewController滚动到对应位置,并且刷新数据,代码示例如下:

php 复制代码
override func viewDidLoad() {
        super.viewDidLoad()
        
        viewModel.getData { model in
            self.configControllers(knowTabs: model?.discTabs ?? [])
        }
        
        categoryView.clickClosure = {index in
            if self.currentIndex < index{
                self.pageViewController.setViewControllers([self.controllers[index]], direction: .forward, animated: true)
            }else{
                self.pageViewController.setViewControllers([self.controllers[index]], direction: .reverse, animated: true )
            }
            self.currentIndex = index
    }

上面代码中configControllers()方法是构建controllers和tabs数据的方法,大致实现如下:

swift 复制代码
private func configControllers(knowTabs:[Tab]){
        if knowTabs.isEmpty{
            return
        }
        controllers.removeAll()
        
        var myTitles = [String]()
        for index in 0..<knowTabs.count{
            let model = knowTabs[index]
            let vc = UIViewController.init()
            controllers.append(vc)
            myTitles.append(model.title)
        }
        
        self.titles = myTitles
    }

至此,极简版通顶分页视图的主要代码便实现完了,如果有什么疑问,欢迎留言向我提问。

相关推荐
奇客软件9 小时前
如何从相机的记忆棒(存储卡)中恢复丢失照片
深度学习·数码相机·ios·智能手机·电脑·笔记本电脑·iphone
GEEKVIP11 小时前
如何修复变砖的手机并恢复丢失的数据
macos·ios·智能手机·word·手机·笔记本电脑·iphone
一丝晨光13 小时前
继承、Lambda、Objective-C和Swift
开发语言·macos·ios·objective-c·swift·继承·lambda
GEEKVIP1 天前
iPhone/iPad技巧:如何解锁锁定的 iPhone 或 iPad
windows·macos·ios·智能手机·笔记本电脑·iphone·ipad
KWMax1 天前
RxSwift系列(二)操作符
ios·swift·rxswift
Mamong1 天前
Swift并发笔记
开发语言·ios·swift
GEEKVIP2 天前
手机使用指南:如何在没有备份的情况下从 Android 设备恢复已删除的联系人
android·macos·ios·智能手机·手机·笔记本电脑·iphone
奇客软件2 天前
如何使用工具删除 iPhone 上的图片背景
windows·ios·智能手机·excel·音视频·cocoa·iphone
安和昂2 天前
【iOS】计算器的仿写
ios
SchneeDuan2 天前
iOS--App启动过程及优化
ios