国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > iOS > 正文

ios電子書(shū)翻頁(yè)效果代碼詳解

2020-07-26 02:30:45
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

近實(shí)現(xiàn)了一個(gè)完整的電子書(shū)閱讀器,支持txt和epub格式的電子書(shū)閱讀,其中epub支持圖文混排的方式展示。本文主要談?wù)勂渲袃煞N翻頁(yè)效果的實(shí)現(xiàn),分別為仿真翻頁(yè)和水平滑動(dòng)翻頁(yè)。

仿真翻頁(yè)

最合適的方案就是使用系統(tǒng)提供的UIPageviewcontroller了,不過(guò)默認(rèn)的UIpageviewcontroller翻頁(yè)時(shí)背面是白色的,而閱讀器通常都會(huì)有背景色或背景圖片,翻頁(yè)時(shí)用戶體驗(yàn)就很糟糕,比如就像下面這樣

所以接下來(lái)主要說(shuō)說(shuō)如何修改背面顏色以達(dá)到美觀的翻頁(yè)效果。

UIpageviewcontroller有一個(gè)屬性叫做isDoubleSided,默認(rèn)為yes,也就是內(nèi)容只會(huì)在單面(正面)顯示,設(shè)置為no后,內(nèi)容便可以正面和背面雙面顯示,這時(shí)每翻一頁(yè),pageview的下面兩個(gè)回調(diào)會(huì)調(diào)用兩次

func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?{  // 第一次回調(diào)索取背面的controller  // 第二次回調(diào)索取正面的controller}func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController?{  // 第一次回調(diào)索取背面的controller  // 第二次回調(diào)索取正面的controller}

所以我們可以對(duì)正面的controller進(jìn)行反向截圖,并將其放在背面的controller上顯示,這樣整體翻頁(yè)效果就會(huì)很美觀了。
代碼示例

// 對(duì)輸入的controller進(jìn)行反向截圖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() }

效果像下面這樣

左右平滑翻頁(yè)

最初采用的是UIpageviewcontroller的另一種翻頁(yè)模式――滾動(dòng)模式。該模式蘋(píng)果在底層是用scrollView實(shí)現(xiàn)的。但這種模式在頁(yè)面切換時(shí)存在一些問(wèn)題,由于蘋(píng)果會(huì)對(duì)相鄰的controller進(jìn)行緩存,當(dāng)調(diào)用open func setViewControllers(_ viewControllers: [UIViewController]?, direction: UIPageViewControllerNavigationDirection, animated: Bool, completion: ((Bool) -> Swift.Void)? = nil)方法并且動(dòng)畫(huà)為true時(shí),有時(shí)蘋(píng)果會(huì)錯(cuò)誤的認(rèn)為它已經(jīng)有了頁(yè)面的緩存而不再執(zhí)行數(shù)據(jù)源方法,從而引發(fā)一些問(wèn)題,更詳細(xì)的說(shuō)明可以看這篇文章,因此決定自己寫(xiě)一個(gè)翻頁(yè)控件

DUATranslationController

DUATranslationController并沒(méi)有采用Scrollview的方式實(shí)現(xiàn),而是基于controller容器,通過(guò)替換child controller來(lái)實(shí)現(xiàn),具體來(lái)說(shuō)就是當(dāng)用戶點(diǎn)擊或者滑動(dòng)時(shí),判斷需要展示上一個(gè)頁(yè)面還是下一個(gè)頁(yè)面,然后模仿UIpageviewcontroller通過(guò)回調(diào)的方式索取controller,加入到controller容器中,并通過(guò)動(dòng)畫(huà)的方式將新的controller平滑移動(dòng)進(jìn)入屏幕,舊的controller同時(shí)移出,如下是單擊手勢(shì)代碼示例(滑動(dòng)手勢(shì)涉及和用戶交互,邏輯更復(fù)雜些,但基本思路是一致的)

@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 {//   滑向上一個(gè)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 {//   滑向下一個(gè)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,切換到某一個(gè)controllerfunc 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)    }       })  } } 

最終效果像這樣:

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 伊川县| 怀来县| 敦煌市| 丹凤县| 临湘市| 定陶县| 衡南县| 蓝山县| 齐河县| 清水河县| 乐陵市| 台安县| 白山市| 宁德市| 阿城市| 桃园市| 恩施市| 达拉特旗| 丹巴县| 泰兴市| 泾源县| 平湖市| 瑞金市| 汕尾市| 盐池县| 德钦县| 任丘市| 永和县| 平陆县| 田林县| 宜城市| 即墨市| 临猗县| 来宾市| 北安市| 蒙自县| 沂水县| 南阳市| 如东县| 恭城| 三河市|