美文网首页UI
iOS中的UIPageViewController

iOS中的UIPageViewController

作者: Longshihua | 来源:发表于2019-03-01 14:43 被阅读0次

    UIPageViewController

    UIPageViewController是一个用来管理内容页之间导航的容器控制器(container view controller),其中每个子页面由子视图控制器管理。内容页间导航可以由用户手势触发,也可以由代码控制。

    UIPageViewController可以实现图片轮播效果和翻书效果.

    初始化PageViewController

    public init(transitionStyle style: UIPageViewController.TransitionStyle,
                navigationOrientation: UIPageViewController.NavigationOrientation,
                              options: [UIPageViewController.OptionsKey : Any]? = nil)
    

    初始化方法提供三个参数:

    • TransitionStyle

    UIPageViewController翻页的过渡样式

      public enum TransitionStyle : Int {
            case pageCurl // Navigate between views via a page curl transition. 卷曲样式类似翻书效果
            case scroll // Navigate between views by scrolling. UIScrollView滚动效果
      }
    
    • NavigationOrientation

    UIPageViewController导航方向

     public enum NavigationOrientation : Int {
            case horizontal // 水平导航
            case vertical // 垂直导航
     }
    
    • UIPageViewController.OptionsKey

    这个参数是可选的,传入的是对UIPageViewController的一些配置

     public struct OptionsKey : Hashable, Equatable, RawRepresentable {
    
            public init(rawValue: String)
     }
    
     extension UIPageViewController.OptionsKey {
    
        public static let spineLocation: UIPageViewController.OptionsKey
        
        // Key for specifying spacing between pages in options dictionary argument to initWithTransitionStyle:navigationOrientation:options:.
        // Value should be a CGFloat wrapped in an NSNumber. Default is '0'.
        // Only valid for use with page view controllers with transition style 'UIPageViewControllerTransitionStyleScroll'.
        @available(iOS 6.0, *)
        public static let interPageSpacing: UIPageViewController.OptionsKey
    }
    
    • spineLocation

    这个key只有在TransitionStyle是翻书效果pageCurl的时候才有作用, 它定义的是书脊的位置,值对应着SpineLocation枚举,默认值为UIPageViewController.SpineLocation.min

     public enum SpineLocation : Int {
            case none // Returned if 'spineLocation' is queried when 'transitionStyle' is not 'UIPageViewControllerTransitionStylePageCurl'.
            case min // Requires one view controller.
            case mid // Requires two view controllers.
            case max // Requires one view controller.
     }
    
    • interPageSpacing

    这个key只有在TransitionStyleUIScrollView滚动效果scroll的时候才有作用, 它定义的是两个页面之间的间距(默认间距是0)

    数据源和代理

    数据源提供了UIPageViewController内容

     weak open var dataSource: UIPageViewControllerDataSource? // If nil, user gesture-driven navigation will be disabled.
    

    UIPageViewControllerDataSource协议

    public protocol UIPageViewControllerDataSource : NSObjectProtocol {
    
        @available(iOS 5.0, *)
        public func pageViewController(_ pageViewController: UIPageViewController,
                                       viewControllerBefore viewController: UIViewController) -> UIViewController?
    
        @available(iOS 5.0, *)
        public func pageViewController(_ pageViewController: UIPageViewController,
                                       viewControllerAfter viewController: UIViewController) -> UIViewController?
    
        @available(iOS 6.0, *)
        // The number of items reflected in the page indicator.
        optional public func presentationCount(for pageViewController: UIPageViewController) -> Int 
    
        @available(iOS 6.0, *)
        // The selected item reflected in the page indicator.
        optional public func presentationIndex(for pageViewController: UIPageViewController) -> Int
    }
    

    协议中包含了四个方法,其中两个为@required,另外两个是@optional.

     public func pageViewController(_ pageViewController: UIPageViewController,
                                       viewControllerBefore viewController: UIViewController) -> UIViewController?
    

    该方法是返回前一个页面,如果返回为nil,那么UIPageViewController就会认为当前页面是第一个页面不可以向前滚动或翻页。当NavigationOrientationhorizontal时,那么该方法获得当前页面左边的视图控制器

    public func pageViewController(_ pageViewController: UIPageViewController,
                                       viewControllerAfter viewController: UIViewController) -> UIViewController?
    

    该方法返回后一个页面,如果返回为nil,那么UIPageViewController就会认为当前页面是最后一个页面不可以向后滚动或翻页。当NavigationOrientationhorizontal时,那么该方法获得是当前页面右边的视图控制器

    代理(delegate)自定义UIPageViewController的行为

    weak open var delegate: UIPageViewControllerDelegate?
    

    UIPageViewControllerDelegate协议

    public protocol UIPageViewControllerDelegate : NSObjectProtocol {
    
        @available(iOS 6.0, *)
        optional public func pageViewController(_ pageViewController: UIPageViewController,
                                                willTransitionTo pendingViewControllers: [UIViewController])
    
        @available(iOS 5.0, *)
        optional public func pageViewController(_ pageViewController: UIPageViewController,
                                                didFinishAnimating finished: Bool,
                                                previousViewControllers: [UIViewController],
                                                transitionCompleted completed: Bool)
    
        @available(iOS 5.0, *)
        optional public func pageViewController(_ pageViewController: UIPageViewController,
                                                spineLocationFor orientation: UIInterfaceOrientation) -> UIPageViewController.SpineLocation
    
    
        @available(iOS 7.0, *)
        optional public func pageViewControllerSupportedInterfaceOrientations(_ pageViewController: UIPageViewController) -> UIInterfaceOrientationMask
    
        @available(iOS 7.0, *)
        optional public func pageViewControllerPreferredInterfaceOrientationForPresentation(_ pageViewController: UIPageViewController) -> UIInterfaceOrientation
    }
    

    协议中有5各方法

    optional public func pageViewController(_ pageViewController: UIPageViewController,
                         willTransitionTo pendingViewControllers: [UIViewController])
    

    该方法是UIPageViewController开始滚动或翻页的时候触发

    optional public func pageViewController(_ pageViewController: UIPageViewController,
                                     didFinishAnimating finished: Bool,
                                         previousViewControllers: [UIViewController],
                                   transitionCompleted completed: Bool)
    

    该方法是在UIPageViewController结束滚动或翻页的时候触发

    optional public func pageViewController(_ pageViewController: UIPageViewController,
                                     spineLocationFor orientation: UIInterfaceOrientation) -> UIPageViewController.SpineLocation
    
    

    该方法在TransitionStylepageCurl并且横竖屏状态变化的时候触发,我们可以重新设置书脊的位置,比如:如果屏幕是竖屏状态的时候我们就设置书脊位置是min或max, 如果屏幕是横屏状态的时候我们可以设置书脊位置是mid

    最后两个方法设置了UIPageViewController支持的屏幕类型

    重要的方法和属性

    isDoubleSided

    属性默认为NO,如果我们当前屏幕仅展示一个页面那么不用设置这个属性,如果设置了UIPageViewControllerSpineLocationMid这个选项,效果是翻开的书这样屏幕展示的就是两个页面,这个属性就必须设置为true了.

    open var isDoubleSided: Bool // Default is 'NO'.
    

    setViewControllers

    open func setViewControllers(_ viewControllers: [UIViewController]?,
                                 direction: UIPageViewController.NavigationDirection,
                                 animated: Bool,
                                 completion: ((Bool) -> Void)? = nil)
    

    这个方法是设置UIPageViewController初始显示的页面,如果doubleSided设为true了,那么viewControllers这个参数至少包含两个视图控制器

    NavigationDirection

    // Only pertains to 'UIPageViewControllerTransitionStylePageCurl'.
    public enum NavigationDirection : Int {
         case forward  // 导航到下一个页面
         case reverse  // 导航到上一个页面
    }
    

    使用

    简单的实现滑动切换视图,即轮播图

    class PageViewController: UIViewController {
    
        // 懒加载创建UIPageViewController
        lazy var pageViewController: UIPageViewController = {
            // 设置水平滚动
            let pageVc = UIPageViewController(transitionStyle: .scroll,
                                              navigationOrientation: .horizontal,
                                              options: nil)
            pageVc.dataSource = self
            pageVc.delegate = self
            return pageVc
        }()
        // 简单的3个UIViewController
        var viewControllers: [UIViewController] {
            return [RedViewController(), YellowViewController(), BlueViewController()]
        }
        var currentIndex: Int = 0
    
        override func viewDidLoad() {
            super.viewDidLoad()
            addPageViewController()
    
            // 设置初始化显示视图控制器
            pageViewController.setViewControllers([viewControllers[currentIndex]],
                                                  direction: .forward,
                                                  animated: true,
                                                  completion: nil)
        }
    
        func addPageViewController() {
            self.addChild(pageViewController)
            pageViewController.view.frame = self.view.frame
            view.addSubview(pageViewController.view)
            pageViewController.didMove(toParent: self)
        }
    }
    

    扩展PageViewController实现数据源和代理协议

    extension PageViewController: UIPageViewControllerDataSource, UIPageViewControllerDelegate {
        func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
            // 显示前一个页面,保证数组不越界
            if currentIndex - 1 >= 0 {
                currentIndex -= 1
                return viewControllers[currentIndex]
            }
            return nil
        }
    
        func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
            // 显示后一个视图页面
            if currentIndex + 1 < viewControllers.count {
                currentIndex += 1
                return viewControllers[currentIndex]
            }
            return nil
        }
    
        func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
            print("willTransition - 开始滚动")
        }
    
        func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
            print("didFinishAnimating - 结束滚动")
        }
    }
    

    实现效果如下

    2.gif

    相关实战

    • Parchment
      68747470733a2f2f73332d75732d776573742d312e616d617a6f6e6177732e636f6d2f70617263686d656e742d73776966742f70617263686d656e742d64656c65676174652e676966.gif
      68747470733a2f2f73332d75732d776573742d312e616d617a6f6e6177732e636f6d2f70617263686d656e742d73776966742f70617263686d656e742d756e73706c6173682e676966.gif

    参考

    UIPageViewController

    相关文章

      网友评论

        本文标题:iOS中的UIPageViewController

        本文链接:https://www.haomeiwen.com/subject/btluzftx.html