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

2025-05-29 0 36

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

仿真翻页

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

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

所以接下来主要说说如何修改背面颜色以达到美观的翻页效果。

uipageviewcontroller有一个属性叫做isdoublesided,默认为yes,也就是内容只会在单面(正面)显示,设置为no后,内容便可以正面和背面双面显示,这时每翻一页,pageview的下面两个回调会调用两次

?

1

2

3

4

5

6

7

8

9

10
func pageviewcontroller(_ pageviewcontroller: uipageviewcontroller, viewcontrollerbefore viewcontroller: uiviewcontroller) -> uiviewcontroller?

{

// 第一次回调索取背面的controller

// 第二次回调索取正面的controller

}

func pageviewcontroller(_ pageviewcontroller: uipageviewcontroller, viewcontrollerafter viewcontroller: uiviewcontroller) -> uiviewcontroller?

{

// 第一次回调索取背面的controller

// 第二次回调索取正面的controller

}

所以我们可以对正面的controller进行反向截图,并将其放在背面的controller上显示,这样整体翻页效果就会很美观了。
代码示例

?

1

2

3

4

5

6

7

8

9

10

11

12

13
// 对输入的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()

}

效果像下面这样

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

左右平滑翻页

最初采用的是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同时移出,如下是单击手势代码示例(滑动手势涉及和用户交互,逻辑更复杂些,但基本思路是一致的)

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66
@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电子书翻页效果代码详解

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 ios电子书翻页效果代码详解 https://www.kuaiidc.com/89683.html

相关文章

发表评论
暂无评论