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

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

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

为了能够更快的完成需求,自己决议不运用相似JXPagingView的完成办法,以极简的办法快速完成需求。同时为了便利与同事间的协作,最终选择了UIPageViewController作为底层的滚动视图来接受各个tab下的uiviewcontroller。

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

接下来我们直接看怎么完成上述效果:

//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滑动手势的代理办法,每次代理事情完毕就刷新数据源

//往左边滑动翻页会走此办法(相似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滚动到对应方位,并且刷新数据,代码示例如下:

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数据的办法,大致完成如下:

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
  }

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