使用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
    }

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

相关推荐
2501_915918411 小时前
iOS性能测试工具 Instruments、Keymob的使用方法 不局限 FPS
android·ios·小程序·https·uni-app·iphone·webview
左左右右左右摇晃4 小时前
Tasker笔记
ios·iphone
恋猫de小郭7 小时前
Android Studio Panda 3 发布,CMP 导致的 Gemini 输入问题
android·ide·flutter·ios·android studio
2501_915918418 小时前
iOS 混淆流程 提升 IPA 分析难度 实现 IPA 深度加固
android·ios·小程序·https·uni-app·iphone·webview
Digitally9 小时前
如何将文件从 Mac / 苹果笔记本传输至 iPad
macos·ios·ipad
2501_9159090610 小时前
React Native 上架 App Store:项目运行与审核构建的流程
android·ios·小程序·https·uni-app·iphone·webview
lzhdim11 小时前
开启iphone的墙纸玻璃效果
macos·ios·objective-c·cocoa·iphone
2501_9159090611 小时前
苹果 Safari 浏览器抓包 页面刷新后的请求分析
android·前端·ios·小程序·uni-app·iphone·safari
2501_9160074720 小时前
网站爬虫原理,基于浏览器点击行为还原可接口请求
前端·javascript·爬虫·ios·小程序·uni-app·iphone
星辰即远方21 小时前
OC学习Foudation框架
学习·ios·objective-c