作为一名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
}
至此,极简版通顶分页视图的主要代码便实现完了,如果有什么疑问,欢迎留言向我提问。