前言
由于公司要开发一款小说类阅读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,即翻动书页的背面。这样就会导致一个非常严重的问题,书页正面页码不连续!“消失”的那一页显示在了上一页背面
那么,如何来优化这个问题呢?方法非常简单,我们再创建一个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 提供的丰富资料。
希望这篇文章可以帮到你。
网友评论
UIPageViewControllerNavigationDirectionReverse 这个是反向切换的意思