使用 UIPageViewController 管理多个 Controller

5,957 阅读4分钟
原文链接: www.jianshu.com

UIPageViewController是于iOS5引入的,它和UITabBarController以及UINavigationController一样,是一个Controller容器,如果你的应用程序有多个在功能上并列的controller,并且之间切换适用UIPageViewController中带有的两种切换效果,那么你可以选择使用它。

一、特点:

UIPageViewController不同于UINavigationController,没有自己的stack来保存以前的controller,可以看出,UIPageViewController的目的是创建一些不需要保存状态的controller,更多是为了展示图片等内容用的,而不是另外一种UINavigationController。

二、使用场景:

1.App启动页
2.控制多个ViewController之间的切换(管理多个Controller)
3.单个ViewController实现多页面效果

效果:

1.图书翻页效果
2.滚动效果


书脊在中间+双面显示.gif


书脊在左+单面显示.gif


滚动翻页切换.gif

三、初始化方法:

NSDictionary *options1 = @{UIPageViewControllerOptionInterPageSpacingKey : @(0)};

UIPageViewController *pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll 
                                                                           navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal 
                                                                                         options:options1];

初始化方法的属性:

  1. TransitionStyle 这个属性是一个枚举:UIPageViewControllerTransitionStyle用来选择UIPageViewController的翻页类型
    typedef NS_ENUM(NSInteger, UIPageViewControllerTransitionStyle) { UIPageViewControllerTransitionStylePageCurl = 0, // 图书翻页效果 UIPageViewControllerTransitionStyleScroll = 1 // 滚动效果};
  2. navigationOrientation翻页方向枚举:UIPageViewControllerNavigationOrientation

    typedef NS_ENUM(NSInteger, UIPageViewControllerNavigationOrientation) { UIPageViewControllerNavigationOrientationHorizontal = 0,//水平方向 UIPageViewControllerNavigationOrientationVertical = 1//竖直方向};
  3. options可选参数,传入配置字典,只有这两个key的配置项:

    UIPageViewControllerOptionSpineLocationKey 
    //这个key只有在style是翻书效果UIPageViewControllerTransitionStylePageCurl的时候才有作用, 它定义的是书脊的位置
    UIPageViewControllerOptionInterPageSpacingKey 
    // 配置两个controller之间的距离,value可传入@(10)

四、主要方法:

设置哪些为当前页面显示的ViewControllers的方法

 - (void)setViewControllers:(nullable NSArray *)viewControllers 
                 direction:(UIPageViewControllerNavigationDirection)direction 
                  animated:(BOOL)animated 
                completion:(void (^ __nullable)(BOOL finished))completion;

主要方法设置翻页(正反向翻页).gif

主要参数:

  1. ViewControllers这里传入一个Controller数组,只有在SpineLocation为UIPageViewControllerSpineLocationMid选项的时候,才需要传入两个Controller(用于正反两面展示不同的controller,而如果书脊居左边或者右边设置就没有意义了),其它的情况,只需要传1个Controller就可以了。
  2. UIPageViewControllerNavigationDirection调用了此方法切换Controller的动画可以为从左往右和从右往左两种,如果animated属性设置为NO,则这个属性无效。是枚举类型,定义了以下两种通过此方法跳转的翻页方式。
    //从左往右(或从下往上)
    UIPageViewControllerNavigationDirectionForward;
    //从左往右(或从下往上);
    UIPageViewControllerNavigationDirectionReverse;

五、翻页效果时用到的重要属性:

  1. SpineLocation
    上面提到过的option的配置选项UIPageViewControllerOptionSpineLocationKey,用来设置书脊的配置项,它的value是个枚举

    typedef NS_ENUM(NSInteger, UIPageViewControllerSpineLocation) { 
    UIPageViewControllerSpineLocationNone = 0, //  
    UIPageViewControllerSpineLocationMin = 1, // 书脊居左或上 
    UIPageViewControllerSpineLocationMid = 2, // 书脊居中。要求要两个controller 
    UIPageViewControllerSpineLocationMax = 3 // 书脊居右或下 };
  2. doubleSided
    这个属性用来控制是否选择双面显示,默认为NO,如果SpineLocation属性设置为UIPageViewControllerSpineLocationMid的话,这个属性就必须设置为YES了,在UIPageViewControllerSpineLocationMid的情况下,当翻页翻到一半的时候展示了一张‘纸’的正反两面(两个Controller)

六、Delegate && Datasource

  • UIPageViewControllerDataSource

    @ required //必须要执行的方法
    1.这个方法是返回前一个页面的controller对象, 如果返回为nil,那么UIPageViewController就会认为当前页面的前面一个页面已经不存在了,那么当前页面是第一个页面,不可以向前滚动或翻页

    - (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController 
                 viewControllerBeforeViewController:(UIViewController *)viewController;

    2.这个方法返回的是当前页面后一个页面的Controller对象
    如果返回nil,那么当前页面就是最后一个页面,不可以再向后翻页

    - (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController 
                  viewControllerAfterViewController:(UIViewController *)viewController;

    @optional 可选执行的方法
    1.此方法在iOS6.0之后被加入,返回page indicator中反映的item的总数.

    - (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController ;

    2.此方法在iOS6.0之后被加入,返回page indicator中反映的当前选择页的位置.

    - (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController ;
  • UIPageViewControllerDelegate

    代理方法都是可选@optional的方法
    1.UIPageViewController开始滚动或翻页的时候触发,参数pendingViewControllers:即将跳往的那个ViewController

         - (void)pageViewController:(UIPageViewController *)pageViewController 
    willTransitionToViewControllers:(NSArray *)pendingViewControllers ;

    2.UIPageViewController已经结束滚动或翻页的时候触发,参数previousViewControllers:当前所显示的ViewController数组(在mid的选项下一个页面显示不止一个ViewController);transitionCompleted:是否完成翻页,还是说做了翻页的手势但是没有翻页成功。

    - (void)pageViewController:(UIPageViewController *)pageViewController 
            didFinishAnimating:(BOOL)finished 
       previousViewControllers:(NSArray *)previousViewControllers 
           transitionCompleted:(BOOL)completed;

    3.这个方法是在style是UIPageViewControllerTransitionStylePageCurl 并且横竖屏状态变化的时候触发,我们可以重新设置书脊的位置,比如如果屏幕是竖屏状态的时候我们就设置书脊位置是UIPageViewControllerSpineLocationMin或UIPageViewControllerSpineLocationMax, 如果屏幕是横屏状态的时候我们可以设置书脊位置是UIPageViewControllerSpineLocationMid

    - (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController 
                       spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation;

    4.设置UIPageViewController支持的屏幕旋转类型,返回参数UIInterfaceOrientationMask:一个枚举类型,用来定义屏幕支持的旋转的类型,比如左旋转:UIInterfaceOrientationMaskLandscapeLeft,支持左旋转屏幕和右旋转屏幕:UIInterfaceOrientationMaskLandscape

    - (UIInterfaceOrientationMask)pageViewControllerSupportedInterfaceOrientations:(UIPageViewController *)pageViewController ;

    5.设置应用程序当前的屏幕的方向 ,返回参数:UIInterfaceOrientation,上下左右四个类型

    - (UIInterfaceOrientation)pageViewControllerPreferredInterfaceOrientationForPresentation:(UIPageViewController *)pageViewController ;

七、总结

  • 如果多个controller是基于同一个底层模板,可以选择使用一个controller,翻页时刷新controller的内容。
  • 如果还需要添加其他组件和UIPageViewController显示在同一个ViewController中,可以在一个ViewController中创建PageViewController并把它当做ChildViewController来使用。