IOS UIPageViewController的相同翻译页bug怎么化解

本人做了简单Epub电子书阅读 使用了 UIPageViewController
和uiwebview相结合,在利用UIPageViewController
的经过被发觉一个题材,UIPageViewController利用代理方
viewControllerBeforeViewController 和 viewControllerAfterViewController
进行前后翻页的操纵,- (void)pageViewController:(UIPageViewController
)pageViewController didFinishAnimating:(BOOL)finished
previousViewControllers:(NSArray
)previousViewControllers
transitionCompleted:(BOOL)completed,此方吗翻页后的回调。当自家于页面进行左右滑行时,进行左右翻页没有问题,翻页后底回调也会见正常应,当自己于page
view里上下滑动时,工程会莫名其妙得调用 而且只是见面调用
viewControllerBeforeViewController
向前翻页的艺术,而翻页后的回调不健康应。。。在初创办的pageview的体系模版里吗闹是题材,大家发出相逢了之么?该怎么解决什么。。

<b>前言 :</b>
为博眼球,所以让了单来问题之题目。但倘若该文是若通过度娘或是古哥检索出来的那么自己充分醒目的告诉您立即就算是若想只要之。想直接扣效能使不思放自己念经的,可一直拉到篇尾那里发生一切代码。
<b>走起 :</b>
之前见腾讯视频、优酷视频的多栏页面做的生好看的,尤其是顶部那么性感的略微黄条,于是乎自己写了只(细节处理好周全的筹划,可一直用去用的哦)。https://github.com/ChuckonYin/news-scroll-title

图片 1

IMG_1390.PNG

为充分利用UIPageViewController的片特色,底部并从未用UIScrollView,但还要使监听pageViewControlle的偏移量。由于pageviewcontroller的贯彻和我们经常举行的巡回轮播原理是一律同等的。所以滑动时监听到的偏移量是无限不靠谱的,最后配合UIPageviewcontrollerDelegate花了酷特别之日成本才好不容易作出一个一如既往的机能来。(这个就是非密切说了,感兴趣的语句可下载者的<a
href=”https://github.com/ChuckonYin/news-scroll-title"&gt;源码&lt;/a&gt;)

  for subView: UIView in view.subviews {
            if subView.isKind(of: UIScrollView.classForCoder()) {
                let tempScrollView = subView as? UIScrollView
                tempScrollView?.delegate = self
            }
        }

此发生只好糟糕处理的是偏移量是“0->375->750->375->0”这种态度的,
由于匪总是,处理起来就那么些难为。
既然,我们出没有发道改者也?在pageviewcontroller中控制器的逻辑切换是连接的。但视图切换在真相上却是无总是的。我们只是免得以透过UIPageViewController的逻辑做一个<b>虚拟偏移量</b>呢?(就比如web开发中React.js写出来的不是实DOM,而是虚拟DOM)。对,就是坏成虚拟偏移量。这个能够实现的语我想以诸多场景我们且是用的上的。下面的话下自家之落实思路:
1、我们设知UIPageViewController有只内嵌的UIScrollView,获取到外,监听到scrollview发生了滚动。具体看上面那段代码。
2、在UIScrollView发生了滚动时,计算起虚拟偏移量。注意我们要的莫是contentoffset,此情景下,那个太操蛋了,不可信(陪合UIPageViewControllerDelegate还是能为此之,逻辑上无比不好操作)。那我们如果什么吗?我们通过时可视的杀viewController的view(取左边距)映射到UIPageViewCOntroller的view上,就可知获偏移量了。而就才是咱真正看到底,想要之偏移量。(<b>核心思想就是使用UIView的convert函数计算真实偏移量</b>)

func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let pageWidth = view.frame.width
        for vc in readyViewControllers!{
            let p = vc.view.convert(CGPoint(), to: view)
//找出屏幕可视范围的控制器视图
            if (p.x) > CGFloat(0.0) && (p.x) < pageWidth{
                let estimatePage = (readyViewControllers?.index(of: vc))!
                estimateOffSetX = CGFloat(estimatePage) * pageWidth - (p.x)
            }
        }
        //若不是循环,最后一个找不到左边距
        if estimateOffSetX >= CGFloat((readyViewControllers?.count)!-1)*pageWidth{
            let p = readyViewControllers?[(readyViewControllers?.count)!-1].view.convert(CGPoint(), to: view)
            estimateOffSetX = CGFloat((readyViewControllers?.count)!-1) * pageWidth - (p?.x)!
        }
//        print("矫正前:\(estimateOffSetX)")
        scrollDidScroll!(estimateOffSetX)
    }

自我们还有零星只问题待留意:
1)最后一个控制器的重新向左滑的时刻,左边去是匪以可张范围外的。需要去丢如下判断标准,单独处理

if (p.x) > CGFloat(0.0) && (p.x) < pageWidth{

2)细心之若肯定发现了方这句判断标准是无保险含0和pageWidth两只临界状态的。那是以当pageviewcontroller滑动到临界状态,会出view的tihuan和contentoffset的面目全非,所以必须放弃。那你恐怕会见说,那还不够精准啊。不急,且看第三步
3、pageviewcontroller当我们松手的时段会到达零界点,我们之所以scrollViewDidEndDecelerating来监听,并做微小的修正

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        let pageWidth = view.frame.width
        currentPage = Int(round(estimateOffSetX/pageWidth))
        if currentPage < 0 {
            currentPage = (readyViewControllers?.count)! - 1
        }
        estimateOffSetX = CGFloat(currentPage)*pageWidth
//        print("矫正后:\(estimateOffSetX)")
        scrollDidScroll!(estimateOffSetX)
    }

完事了,如此一来我们能得到一个虚拟偏移量(从另外一个角度来拘禁,这才是实的),变化历程是如此的:
0->10->30->100->200->300->375->380->400->500->600->750->800->990->1040->1170->1200->1400->1600->1800。
上啊噜,这才是咱们纪念要之呦。也难怪apple的pageviewcontroller并无露scrollview属性,因为无可用什么。这样同样改就可用了。

Talk is Cheap,Show you the Code👇:

import UIKit
class CYPageViewController: UIPageViewController, UIPageViewControllerDelegate, UIScrollViewDelegate {
   private var tempDelegate: UIPageViewControllerDelegate?


   private var currentPage: Int = 0

   private var scrollDidScroll: ((CGFloat)->Void)?

   private var readyViewControllers: [UIViewController]?

   private var estimateOffSetX: CGFloat = 0

   override func viewDidLoad() {
       super.viewDidLoad()
       for subView: UIView in view.subviews {
           if subView.isKind(of: UIScrollView.classForCoder()) {
               let tempScrollView = subView as? UIScrollView
               tempScrollView?.delegate = self
           }
       }
   }

   func addListenerWithReadyViewControllers(_ readyViewControllers: [UIViewController], didScroll scrollDidScroll: @escaping (CGFloat)->Void){
       self.readyViewControllers = readyViewControllers
       self.scrollDidScroll = scrollDidScroll
   }

   func scrollViewDidScroll(_ scrollView: UIScrollView) {
       let pageWidth = view.frame.width
       for vc in readyViewControllers!{
           let p = vc.view.convert(CGPoint(), to: view)
           if (p.x) > CGFloat(0.0) && (p.x) < pageWidth{
               let estimatePage = (readyViewControllers?.index(of: vc))!
               estimateOffSetX = CGFloat(estimatePage) * pageWidth - (p.x)
           }
       }
       //若不是循环,最后一个找不到左边距
       if estimateOffSetX >= CGFloat((readyViewControllers?.count)!-1)*pageWidth{
           let p = readyViewControllers?[(readyViewControllers?.count)!-1].view.convert(CGPoint(), to: view)
           estimateOffSetX = CGFloat((readyViewControllers?.count)!-1) * pageWidth - (p?.x)!
       }
//        print("矫正前:\(estimateOffSetX)")
       scrollDidScroll!(estimateOffSetX)
   }

   func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
       let pageWidth = view.frame.width
       currentPage = Int(round(estimateOffSetX/pageWidth))
       if currentPage < 0 {
           currentPage = (readyViewControllers?.count)! - 1
       }
       estimateOffSetX = CGFloat(currentPage)*pageWidth
//        print("矫正后:\(estimateOffSetX)")
       scrollDidScroll!(estimateOffSetX)
   }
}

import UIKit

class ViewController: UIViewController, UIPageViewControllerDelegate, UIPageViewControllerDataSource {

   private var pageCtrl: CYPageViewController = CYPageViewController.init(transitionStyle: UIPageViewControllerTransitionStyle.scroll, navigationOrientation: UIPageViewControllerNavigationOrientation.horizontal, options: nil)

   lazy var viewControllers: [UIViewController] = {
       var arr = Array<UIViewController>()
       let color = [UIColor.red, UIColor.green, UIColor.brown, UIColor.yellow]
       for i in 0...3{
           let vc = UIViewController()
           vc.view.backgroundColor = color[i]
           arr.append(vc)
       }
       return arr
   }()

   override func viewDidLoad() {
       super.viewDidLoad()

       pageCtrl.view.frame = self.view.bounds
       view.addSubview(pageCtrl.view)

       pageCtrl.setViewControllers([viewControllers[0]], direction: UIPageViewControllerNavigationDirection.forward, animated: false) { (cp) in

       }
       pageCtrl.delegate = self
       pageCtrl.dataSource = self

       pageCtrl.addListenerWithReadyViewControllers(viewControllers) { (x) in
           print("修复后的偏移量___\(x)")
       }
   }

   func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
       let index = viewControllers.index(of: viewController)
       if index == 0 {
//            return viewControllers[viewControllers.count-1]
           return nil;
       }
       return viewControllers[index!-1]
   }
   func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
       let index = viewControllers.index(of: viewController)
       if index == viewControllers.count-1 {
//            return viewControllers[0]
           return nil;
       }
       return viewControllers[index!+1]
   }
}

如上是整代码,代码量少copy吧

<b>写在最终 :</b>
see,其实若独自调用了如下一句代码就取到了而想如果的,是无是坏nice。即便是采取到即档面临,污染也是极致小极小之。如果你说你用UIScrollView替换了,那我报告您UITableView、UICollectionView你吧足以好写复用机制用UIScrollView替换,但那样会好low。存在即发生价。
关于OC版的,这几乎词代码我思念你几分钟便可知翻译了底

 pageCtrl.addListenerWithReadyViewControllers(viewControllers) { (x) in
            print("修复后的偏移量___\(x)")
        }

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图