ios电子书翻页效果代码详解

近实现了一个完整的电子书阅读器,支持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时,有时苹果会错误的认为它已经有了页面的缓存而不再执行数据源方法,从而引发一些问题,更详细的说明可以看这篇文章,因此决定自己写一个翻页控件

DUATranslationController

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

@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实现翻页效果动画实例代码
  • iOS图片界面翻页切换效果
  • iOS实现日历翻页动画
  • 实例讲解iOS中的UIPageViewController翻页视图控制器
(0)

相关推荐

  • 实例讲解iOS中的UIPageViewController翻页视图控制器

    一.引言 UIPageViewController是iOS中少见的动画视图控制器之一,通过它既可以创建类似UIScrollView与UIPageControl结合的滚屏视图,也可以创建类似图书效果的炫酷翻页视图. UIPageViewController在iOS 5 SDK中首次引入,它使得开发者可以使用这个ViewController创建分页视图.在iOS 6中,这个类有了更新,支持滚动过渡效果.使用Page View,用户可以方便的通过手势在多个页面之间导航.UIPageViewContro

  • iOS实现日历翻页动画

    本文我主要描述两方面: 1.日历(简单描述原理) 2.翻页动画(重点) 最终的效果如下图:     图中沿四个对角的翻页动画,代表对应方向手势的滑动 1. 日历 要实现一个日历,其实原理很简单,我们只要知道三个数据: 1.今天是哪一天 2.这个月的第一天是星期几(哪天) 3.这个月总共有多少天 根据这个三个数据,就可以把得到的日期显示在日历上了,至于日历用什么来显示,我个人比较喜欢用UICollectionView,一个cell代表一天,当然也可以用很多个label,button来显示. 1.获

  • iOS图片界面翻页切换效果

    先看效果: 下面贴代码: #import "ViewController.h" @interface ViewController () @property (weak, nonatomic) IBOutlet UIImageView *backgroundView; @property (strong,nonatomic) NSArray *array; @end @implementation ViewController -(NSArray *)array { if (_arra

  • iOS实现翻页效果动画实例代码

    大体思路: 在self.view 上放置一个label,label.text从数组中获得,当点击上下页按钮的时候,改变label.text,并且执行翻页效果动画. 效果如图: 主要代码: #pragma mark - 下一页按钮响应事件 - (void)nextPage:(UIButton *)btn { _forwardBtn.enabled = YES; if (_count<_arr.count-1) { btn.enabled = YES; _label.text = [_arr obj

  • ios电子书翻页效果代码详解

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

  • javascript移动端 电子书 翻页效果实现代码

    这篇文章主要介绍了javascript移动端 电子书 翻页效果实现代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 效果 1.后端给一长串的纯文本 2.前端根据屏幕的高度,将文本切割为 n 页 3.使用插件 turn.js 将切割好的每页,加上翻书效果 代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&q

  • JS实现的3D拖拽翻页效果代码

    本文实例讲述了JS实现的3D拖拽翻页效果.分享给大家供大家参考,具体如下: 以前看到一个很火的帖子,拖拽实现的翻页效果,非常的有创意,自己也很喜欢,于是乎就萌发了用自己的方法模仿的想法.感谢原创作者的创意,结果一样,但过程不一样哦.奉上代码,供大家参考. 运行效果截图如下: 在线演示地址如下: http://demo.jb51.net/js/2015/js-3d-drag-page-style-codes/ 具体代码如下: <!DOCTYPE html PUBLIC "-//W3C//DT

  • JavaScript 拖拽翻页效果代码

    拖拽翻页效果JavaScript特效-demo by http://www.jb51.net html,body{ width:100%; height:100%; border:0px; margin:0px; overflow:hidden; } #menu{ width:1000px; height:500px; overflow:hidden; background:lightblue; } .page{ position:absolute; width:300px; height:40

  • JQuery标签页效果实例详解

    本文实例讲述了JQuery标签页效果实现方法.分享给大家供大家参考,具体如下: 第一个标签页中鼠标滑过显示不同的标签页,第二个标签页中点击不同标签加载其他页面中的内容,加载等待的图片缓慢隐藏,效果图如下: /WebRoot/4.Tab.html: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> &l

  • Android自定义控件eBook实现翻书效果实例详解

    本文实例讲述了Android自定义控件eBook实现翻书效果的方法.分享给大家供大家参考,具体如下: 效果图: Book.java文件: package com.book; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.ImageView; public class Book extend

  • C# winform自定义翻页控件详解

    C#  winform中自定义的翻页控件,自己设计,供大家参考,具体内容如下 1.主要是使用控件绑定点击事件   用到的控件分别为picturebox   lable  上一页pbPage_Prev    下一页 pbPage_Next  首页 pbPage_Begin   尾页pbPage_End  是picturebox控件加背景图 "第  页/ 共  页" 是一个lable "labPageInfo"    在lable上面加了一个隐藏的textbox 控件

  • 留言板翻页的实现详解

    我们在留言板的设计中,遇到的最大问题就是如何让留言板具有翻页功能,而且可以自动判断是否到了最后一页,下面我就将我在设计留言板时用到的技术与大家分享: 首先连接数据库,这里就不讲了,下面就将每一条语句作详细的说明. <?         .         .         . $query="select * from note order by sendtime desc";  #按时间将留言排序 $total=mysql_numrows($result);#计算总共有多少条

  • DEDECMS实用漂亮的翻页效果修改方法第1/3页

    在网上流传很广,坛子里也有几个人都转过,这里说下怎么用(教程以默认模板为例). 一.内容页分页代码修改 首先介绍下基础知识,dede的内容页调用标记是: 复制代码 代码如下: <div class="cupage">{dede:pagebreak/}</div> 生成html后形式为: 复制代码 代码如下: <div class="cupage"><a href='#'>上一页</a><strong&

随机推荐