美文网首页苹果之美iOS DeveloperiOS新手学习
iOS电子书阅读器之优雅的翻页效果实现

iOS电子书阅读器之优雅的翻页效果实现

作者: 还是不够辣 | 来源:发表于2018-01-15 14:04 被阅读1494次

最近实现了一个完整的电子书阅读器,支持txt和epub格式的电子书阅读,其中epub支持图文混排的方式展示。本文主要谈谈其中两种翻页效果的实现,分别为仿真翻页和水平滑动翻页。完整的电子书阅读器项目在这里

仿真翻页

最合适的方案就是使用系统提供的UIPageviewcontroller了,不过默认的UIpageviewcontroller翻页时背面是白色的,而阅读器通常都会有背景色或背景图片,翻页时用户体验就很糟糕,比如就像下面这样


image1.png

所以接下来主要说说如何修改背面颜色以达到美观的翻页效果。
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时,有时苹果会错误的认为它已经有了页面的缓存而不再执行数据源方法,从而引发一些问题,更详细的说明可以看这篇文章,因此决定自己写一个翻页控件DUATranslationController

DUATranslationController并没有采用Scrollview的方式实现,而是基于controller容器,通过替换child controller来实现,具体来说就是当用户点击或者滑动时,判断需要展示上一个页面还是下一个页面,然后模仿UIpageviewcontroller通过回调的方式索取controller,加入到controller容器中,并通过动画的方式将新的controller平滑移动进入屏幕,旧的controller同时移出,如下是单击手势代码示例(滑动手势涉及和用户交互,逻辑更复杂些,但基本思路是一致的,详细可看DUATranslationController源码

@objc func handleTapGes(gesture: UITapGestureRecognizer) -> Void {
        let hitPoint = gesture.location(in: gesture.view)
        let curController = self.childViewControllers.first!
        
        if hitPoint.x < gesture.view!.frame.size.width/3 {
//            滑向上一个controller
            let lastController = self.delegate?.translationController(translationController: self, controllerBefore: curController)
            if lastController != nil {
                self.delegate?.translationController(translationController: self, willTransitionTo: lastController!)
                self.setViewController(viewController: lastController!, direction: .right, animated: allowAnimating, completionHandler: {(complete) in
                    self.delegate?.translationController(translationController: self, didFinishAnimating: complete, previousController: curController, transitionCompleted: complete)
                })
            }
            
        }
        if hitPoint.x > gesture.view!.frame.size.width*2/3 {
//            滑向下一个controller
            let nextController: UIViewController? = self.delegate?.translationController(translationController: self, controllerAfter: self.childViewControllers.first!)
            if nextController != nil {
                self.delegate?.translationController(translationController: self, willTransitionTo: nextController!)
                self.setViewController(viewController: nextController!, direction: .left, animated: allowAnimating, completionHandler: {(complete) in

                    self.delegate?.translationController(translationController: self, didFinishAnimating: complete, previousController: curController, transitionCompleted: complete)
                })
            }
            
        }
        
    }
// 该方法模仿UIpageviewcontroller,切换到某一个controller
func setViewController(viewController: UIViewController, direction: translationControllerNavigationDirection, animated: Bool, completionHandler: ((Bool) -> Void)?) -> Void {
        if animated == false {
            // 直接添加child controller ,略
        }else {
            let oldController = self.childViewControllers.first
            self.addController(controller: viewController)
            
            var newVCEndTransform: CGAffineTransform
            var oldVCEndTransform: CGAffineTransform
            viewController.view.transform = .identity
            if direction == .left {
                viewController.view.transform = CGAffineTransform(translationX: screenWidth, y: 0)
                newVCEndTransform = .identity
                oldController?.view.transform = .identity
                oldVCEndTransform = CGAffineTransform(translationX: -screenWidth, y: 0)
            }else {
                viewController.view.transform = CGAffineTransform(translationX: -screenWidth, y: 0)
                newVCEndTransform = .identity
                oldController?.view.transform = .identity
                oldVCEndTransform = CGAffineTransform(translationX: screenWidth, y: 0)
            }
            
            UIView.animate(withDuration: animationDuration, animations: {
                oldController?.view.transform = oldVCEndTransform
                viewController.view.transform = newVCEndTransform
            }, completion: { (complete) in
                if complete {
                    self.removeController(controller: oldController!)
                }
                if completionHandler != nil {
                    completionHandler!(complete)
                }
                
            })
        }
    }
    

最终效果像这样:


左右平滑翻页

相关文章

  • iOS电子书阅读器之优雅的翻页效果实现

    最近实现了一个完整的电子书阅读器,支持txt和epub格式的电子书阅读,其中epub支持图文混排的方式展示。本文主...

  • 视觉 - (1)OpenGL 初识

    前言:我做ios和android开发也很多年了,之前也用OpenGL做过一些效果,比如阅读器的翻页效果。但是一直没...

  • 阅读器多种翻页的设计与实现

    前言 前文介绍的是小说阅读器的设计和实现,本文作为补充对多种翻页模式做详细剖析。 正文 常见的阅读器翻页模式包括:...

  • "任阅" 网络小说阅读器源码

    "任阅" 网络小说阅读器,实现追书推荐收藏、书籍/标签检索、模拟翻书的翻页效果、缓存书籍、日夜间模式、书签、txt...

  • iOS上类似驾考宝典覆盖翻页的控件SZPageControlle

    SZPageController是仿UITableView接口所实现的类似于驾考宝典覆盖翻页,小说阅读器覆盖翻页效...

  • iOS实现翻页效果动画

    项目里面有一个接受消息然后将消息内容以翻页的形式展现给用户,返回的数据就是简单的文字没有图片,所以我就简单的用了t...

  • 平时的记录,待整理

    电子书阅读器开发 (一) 10分钟适配 iOS 11 & iPhone X ios - 用UICollection...

  • 听书与播客

    这是「阅读」系列之五 本文结构: 电子书阅读器+TTS听书神器 电子书阅读器+真人原文朗读懒人听书 真人原文朗读❶...

  • Kindle

    Kindle Voyage电子书阅读器标准版:300 ppi电子墨水触控屏、内置智能调节阅读灯、创新【压敏式翻页键...

  • 【Android 进阶】仿抖音系列之列表播放视频(二)

    上一篇中,我们实现了仿抖音上下翻页切换视频的效果,详见【Android 进阶】仿抖音系列之翻页上下滑切换视频(一)...

网友评论

    本文标题:iOS电子书阅读器之优雅的翻页效果实现

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