近实现了一个完整的电子书阅读器,支持txt和epub格式的电子书阅读,其中epub支持图文混排的方式展示。本文主要谈谈其中两种翻页效果的实现,分别为仿真翻页和水平滑动翻页。
仿真翻页
最合适的方案就是使用系统提供的UIPageviewcontroller了,不过默认的UIpageviewcontroller翻页时背面是白色的,而阅读器通常都会有背景色或背景图片,翻页时用户体验就很糟糕,比如就像下面这样

所以接下来主要说说如何修改背面颜色以达到美观的翻页效果。
UIpageviewcontroller有一个属性叫做isDoubleSided,默认为yes,也就是内容只会在单面(正面)显示,设置为no后,内容便可以正面和背面双面显示,这时每翻一页,pageview的下面两个回调会调用两次
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?
{
// 第一次回调索取背面的controller
// 第二次回调索取正面的controller
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController?
{
// 第一次回调索取背面的controller
// 第二次回调索取正面的controller
}
所以我们可以对正面的controller进行反向截图,并将其放在背面的controller上显示,这样整体翻页效果就会很美观了。
代码示例
// 对输入的controller进行反向截图
func grabViewController(viewController: DUAPageViewController) -> Void {
self.index = viewController.index
self.chapterBelong = viewController.chapterBelong
let rect = viewController.view.bounds
UIGraphicsBeginImageContextWithOptions(rect.size, true, 0.0)
let context = UIGraphicsGetCurrentContext()
let transform = CGAffineTransform(a: -1.0, b: 0.0, c: 0.0, d: 1.0, tx: rect.size.width, ty: 0.0)
context?.concatenate(transform)
viewController.view.layer.render(in: context!)
self.backImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
效果像下面这样

左右平滑翻页
最初采用的是UIpageviewcontroller的另一种翻页模式——滚动模式。该模式苹果在底层是用scrollView实现的。但这种模式在页面切换时存在一些问题,由于苹果会对相邻的controller进行缓存,当调用open func setViewControllers(_ viewControllers: [UIViewController]?, direction: UIPageViewControllerNavigationDirection, animated: Bool, completion: ((Bool) -> Swift.Void)? = nil)方法并且动画为true时,有时苹果会错误的认为它已经有了页面的缓存而不再执行数据源方法,从而引发一些问题,更详细的说明可以看这篇文章,因此决定自己写一个翻页控件










