UIPageViewController使用 分享笔记

作者: 巫师学徒 | 来源:发表于2016-09-01 14:42 被阅读1864次

    前言

    由于公司要开发一款小说类阅读APP,其中体验上非常重要的一点便是翻页效果。为了实现翻页效果,我查询了很多资料后选择使用了UIPageViewController。原因很简单,使用方便,功能强大,开发速度快。首先,我们先看看翻页效果图:

    翻页效果展示图

    结构

    在使用UIPageViewController前,我们应该先搞清楚它的层次结构。(这里是我在使用过程中的理解,如有不对,欢迎指出)。


    pageviewcontroller层次展示图

    UIPageViewController作为子控制器加载在viewController上。作为文本控制器的容器,且提供翻页的动画效果。

    创建一个TextViewController,用来显示文本,装入pageViewController中。

    所以,pageViewController只是提供一个翻页特效的容器,真正显示在界面上的是里面的TextViewController。到这里是我对pageViewController有一个初步的理解。

    使用

    1.初始化

    - (instancetype)initWithTransitionStyle:(UIPageViewControllerTransitionStyle)style navigationOrientation:(UIPageViewControllerNavigationOrientation)navigationOrientation options:(nullable NSDictionary*)options
    

    UIPageViewController 为我们提供了2种翻页样式,一种是拟真一种是滚动。只需要使用系统的构造方法返回一个UIPageViewController的对象。并且设置它的代理和数据源并把它加入到控制器中就可以了

    pageViewController.delegate = self;
    
    pageViewController.dataSource = self;
    
    [self addChildViewController:pageViewController];
    
    [self.view addSubview:pageViewController.view];
    

    通过提供的set方法将textController装入pageViewController中,这个set方法提供了一种样式,决定翻页是纵向还是横向。

    typedef NS_ENUM(NSInteger, UIPageViewControllerNavigationDirection) {
    
    UIPageViewControllerNavigationDirectionForward,//横向,像书一样
    
    UIPageViewControllerNavigationDirectionReverse//纵向,像日历一样
    };
    
    BookTextController *readerController = [BookTextController new];//展示文本的控制器
        [_pageViewController setViewControllers:@[ readerController ]
                                      direction:UIPageViewControllerNavigationDirectionForward
                                       animated:NO
                                     completion:nil];
    

    2.delegate和dataSource

    //向前翻页
    - (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController;
    
    //向后翻页
    - (nullable UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController;
    

    从声明中我们不难发现返回的是一个UIViewController对象,这个对象将重新装入pageViewController中,从而显示在界面上。其中参数中的viewController为当前显示的控制器(这个参数在使用doubleSided属性时非常重要,后面会讲到)。知道这2个方法的作用后,pageViewController使用起来就非常简单了。

    并且这个方法执行以后,之前pageViewController里的控制器将被释放,所以pageViewController.viewControllers同样只装了1个viewController。

    - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
           viewControllerAfterViewController:(UIViewController *)viewController {
        //返回即将显示的控制器
        BookTextController *vc = [BookTextController new];
        return vc;
    }
    

    还有一个非常有用的代理,它在动画执行完毕后被调用,在controller切换完成后,我们可以在这个代理中进行一些后续操作。例如用UIPageViewController实现轮播分页等功能。

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

    到这里pageViewController的基本使用已经差不多了。通过合理的设置,我们很容易就可以实现一个翻页效果。但是在开发阅读软件中我还遇到一个非常严重的体验问题。在翻页的时候,书页背面的颜色默认为白色。在黑夜模式中非常“辣眼睛”

    黑夜模式书页背面为白色 ![Uploading 1F5EC677-326D-4BAF-96D6-5A885FA07C9F_639563.png . . .]

    3.解决翻页模式书页背面“辣眼睛”->doubleSided

    顾名思义,doubleSided这个属性开启后,书页的正反两面都将显示文本。

    开启这个属性后,dataSource中的那两个方法会执行2次。

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

    第一次执行viewController和之前一样是正在翻动的书页的正面,第二次执行时viewController则是第一次return出去的ViewController,即翻动书页的背面。这样就会导致一个非常严重的问题,书页正面页码不连续!“消失”的那一页显示在了上一页背面

    1F5EC677-326D-4BAF-96D6-5A885FA07C9F.png 9B291FCF-5570-45F3-87DA-940FD207352F.png

    那么,如何来优化这个问题呢?方法非常简单,我们再创建一个BackViewController(这里参考了github上一个demo:
    https://github.com/mattabras/DoubleSidedPageViewController
    BackViewController源码可以直接去上面下载。)

    BackViewController上只有一个大小为屏幕大小的UIImageView,在第一次进入时,将参数viewController的view作为图片设置到BackViewController的UIImageView里。返回给pageViewController。第二次才返回要显示的viewController。

    - (UIViewController *)pageViewController:(UIPageViewController *)pageViewController
          viewControllerBeforeViewController:(UIViewController *)viewController {
        /**
         *  backviewcontroller->截屏当前控制器view,显示在当前页背面
         */
        if([viewController isKindOfClass:[BookTextController class]]) {
            self.currentViewController = viewController;
            
            LZBackViewController *backViewController = [LZBackViewController new];
            [backViewController updateWithViewController:viewController];
            return backViewController;
        }
        /**
         *  重新加载新的一章或一页到lzbooktextcontroller上 并返回给pageviewcontroller
         */    
        LZBackViewController *showVc =  (LZBackViewController *)self.currentViewController;
        return showVc;
    }
    

    到这里我们解决了黑夜模式书页背面辣眼睛的体验问题了。

    小结

    使用UIPageViewController主要就是理解其层次结构和代理方法调用时机。作为容器加载各式各样的显示控制器。在此特别感谢一起开发阅读APP的战友小明同学 @GeekDmm 提供的丰富资料。
    希望这篇文章可以帮到你。

    相关文章

      网友评论

      • yangyoungya:UIPageViewControllerNavigationDirectionForward 这个是正向切换的意思吧
        UIPageViewControllerNavigationDirectionReverse 这个是反向切换的意思
        巫师学徒:@yangyoungya 不好意思 之前看错了 实际效果就是一个跟翻书一样 一个跟翻日历一样 实际就是一个横向 一个纵向 你可以写个demo试一下
        yangyoungya:@巫师学徒 对,但是你文章里写的是一个是横向,一个是纵向的:smile:
        巫师学徒:一个向前翻页 一个向后翻 对应动画
      • 墙角一枝梅5:大神,写的代码很棒👍,发现一个bug,就是“解决翻页模式书页背面“辣眼睛”->doubleSided”,这个确实解决了翻页模式书页背面的颜色,但是背面的文字不对了,从右往左翻页是对的,但是从左往右翻页就不对了。从左往右翻页时,背面文字显示的是下一章的文字,不是正在翻的这一张的文字,请问大神怎么解决
      • 十一遥:UIPageViewControllerNavigationDirectionForward 和 UIPageViewControllerNavigationDirectionReverse 都是书本仿真模式的翻页,翻页动画效果是,从右向左/ 从左向右, 并不是日历效果的纵向翻页
        巫师学徒:@十一妖 这种最常用 只演示了这种 你可以自己在demo里改一下那些参数 翻页方向 样式都可以设置的
        十一遥:@巫师学徒 我看我们项目里 就是横这翻页, UIPageViewControllerNavigationDirectionForward翻到下一页动画效果,UIPageViewControllerNavigationDirectionReverse翻到上一页动画效果.
        巫师学徒:@十一妖 你看有一个是竖着的啊 家里挂的日历翻页其实跟翻书也差不多 就是方向不一样而已
      • Roger_max:求一个demo :smiley:
      • TongRy:你好,请问下,你是怎么做分页的呢?
        春夏秋冬和你:@TongRy https://github.com/TigerWf/WFReader 还有个网络版https://github.com/TigerWf/EReader 但是没服务端 看不到效果 两份分页逻辑是一样的 基于coretext实现的
        TongRy:@巫师学徒 有demo吗,现在卡这里了:sob:
        巫师学徒:@TongRy 根据渲染大小 切割数据源
      • 天蝎座沫沫:你好,我想知道怎么跳转到特定的页,我想做成驾考宝典那种样式的 QQ:3383044581
      • 屮艸芔:请问在阅读器里章节切换是怎么处理的呀
        巫师学徒:@屮艸芔 展示界面的核心是return的controller,如果判断是最后一页,下一次返回的就应该是下一章的第一页内容
        屮艸芔:@巫师学徒 下一章的内容已经请求到了,但是我不知道什么时候把新内容展示出来,每个章节内容需要的页数是固定的,但是我看有些阅读器在一个章节的最后一页翻开的时候已经可以看到下一章的内容了,这个是怎么做的呢
        巫师学徒:@屮艸芔 这和你解析文本逻辑相关,如果你当前章节的内容已经是最后一页了,你就需要从本地/网络请求下一章内容
      • BugChester:牛逼呀,我曹,老司机带带我。。。
      • 辉的书:你好,请问有没有遇到过翻页翻到空白页,还有就是文本能不能进行编辑(UIMenuController) ? :flushed:
        巫师学徒:@辉的书 翻页内容和文本编辑都是在显示的controller里处理的
      • 我家石榴:66666写得简直太棒了~~~~膜拜大神,老司机带带我吧~~~
      • GeekDmm:6666 战友前来报道

      本文标题:UIPageViewController使用 分享笔记

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