Get custom read direction in UIPageViewController

The two methods viewControllerBeforeViewController and viewControllerAfterViewController UIPageViewControllerDataSource do not indicate the direction of movement.

The delegate transitionCompleted method of the UIPageViewController doesn't help us either. It just says if the page has been completely cleaned.

So, which method should I use to pinpoint the direction of the user (left or right)?

Perhaps these two properties may help:

 let directionForward = UIPageViewControllerNavigationDirection.Forward let directionReverse = UIPageViewControllerNavigationDirection.Reverse 

My code is as follows:

 import UIKit class ProView: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate { var pageViewController: UIPageViewController? let characterImages = ["character1", "character2", "character1", "character2", "character1", "character2", "character1", "character2"] override func viewDidLoad() { super.viewDidLoad() createPageViewController() setupPageControl() character = 1 } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } // Forward, check if this IS NOT the last controller func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController ProView: UIViewController) -> UIViewController? { let itemController = ProView as PageItemController // Check if there is another view if itemController.itemIndex+1 < characterImages.count { return getItemController(itemController.itemIndex+1) } return nil } // Check if this IS NOT the first controller func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController ProView: UIViewController) -> UIViewController? { let itemController = ProView as PageItemController if itemController.itemIndex < 0 { return getItemController(itemController.itemIndex-1) } return nil } private func getItemController(itemIndex: Int) -> PageItemController? { if itemIndex < characterImages.count { let pageItemController = self.storyboard!.instantiateViewControllerWithIdentifier("ItemController") as PageItemController pageItemController.itemIndex = itemIndex pageItemController.imageName = characterImages[itemIndex] return pageItemController } return nil } func createPageViewController() { let pageController = self.storyboard!.instantiateViewControllerWithIdentifier("PageController") as UIPageViewController pageController.dataSource = self pageController.delegate = self if characterImages.count > 0 { let firstController = getItemController(0)! let startingViewControllers: NSArray = [firstController] pageController.setViewControllers(startingViewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil) } pageViewController = pageController addChildViewController(pageViewController!) self.view.addSubview(pageViewController!.view) pageViewController?.didMoveToParentViewController(self) } func setupPageControl() { let appearance = UIPageControl.appearance() appearance.pageIndicatorTintColor = UIColor.grayColor() appearance.currentPageIndicatorTintColor = UIColor.whiteColor() } func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int { return characterImages.count } func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int { } // BETA func pageViewController(PageItemController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers pageViewController: [AnyObject], transitionCompleted completed: Bool) { if (!completed) { // You do nothing because whatever page you thought // the book was on before the gesture started is still the correct page return; } // This is where you would know the page number changed and handle it appropriately character = workaround } } class PageItemController: UIViewController { @IBOutlet weak var imageCharacterChoose: UIImageView! var itemIndex: Int = 0 var imageName: String = "" { didSet { if let imageView = imageCharacterChoose {imageCharacterChoose.image = UIImage(named: imageName) } } } } 

According to what pbasdf said,

 var currentIndex: Int = 0 var nextIndex: Int = 0 func pageViewController(PageItemController: UIPageViewController, willTransitionToViewControllers pageViewController: [AnyObject]) { // pageViewController is the pending View Controller nextIndex = currentIndex // pageViewController...... how do I get its index? } 
+9
source share
5 answers

You should use the delegate methods willTransitionToViewControllers: and didFinishAnimating: to determine if the transition is forward or backward. Declare a pair of index variables at the beginning of your class, say currentIndex and nextIndex (both Int ).

In the willTransitionToViewControllers method willTransitionToViewControllers set nextIndex to the itemIndex pending controller:

EDIT

 func pageViewController(pageViewController: UIPageViewController, willTransitionToViewControllers pendingViewControllers: [AnyObject]) { // the page view controller is about to transition to a new page, so take note // of the index of the page it will display. (We can't update our currentIndex // yet, because the transition might not be completed - we will check in didFinishAnimating:) if let itemController = pendingViewControllers[0] as? PageItemController { nextIndex = itemController.itemIndex } } 

End edit

At this point, you can decide whether to go forward or backward: if nextIndex > currentIndex , and then forward; if nextIndex < currentIndex then back. Then in didFinishAnimating , if completed true (so it completed the transition to the next view controller), set currentIndex to nextIndex so you can use currentIndex wherever you need to specify which page is currently on the screen:

EDIT

 func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [AnyObject], transitionCompleted completed: Bool) { if (completed) { // the page view controller has successfully transitioned to the next view // controller, so we can update our currentIndex to the value we obtained // in the willTransitionToViewControllers method: currentIndex = nextIndex } } 

Note that the first argument to these methods is pageViewController (an instance of UIPageViewController), not the pageItemController that you have in your current code.

Finally, just note: this enumeration to which you refer ( UIPageViewControllerNavigationDirection ) is used only in the setViewControllers(_, direction:) method.

End edit

+21
source

Assuming you have a local ViewControllers array, you can use this delegate method:

 func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { guard let current = self.viewControllers?.first else { // TODO handle error return } guard let index = self.pages.firstIndex(of: current) else { // TODO handle error return } self.currentIndex = index } 

guard statements should not fail, but just in case ....

+1
source

In my case, I was able to determine the scroll direction using only the func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [AnyObject], transitionCompleted completed: Bool) .

Here is how. Suppose you already have a way to reference the current index called currentIndex . In the above method, you already have information about previousViewControllers ViewViewControllers so you can get the previous index named previousIndex .

Essentially, here is an implementation inside the delegate method:

 func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [AnyObject], transitionCompleted completed: Bool) { if completed { if previousIndex < currentIndex { // forward } else if previousIndex > currentIndex { // reverse } } } 
+1
source

It is not possible to determine if the user has been moved forward or backward.

You need to use these two methods to represent the views before and after:

pageViewController: viewControllerBeforeViewController:

pageViewController: viewControllerAfterViewController:

You can track the index by adding a property to viewControllers, and then you can compare pageIndexes.

0
source

First, in your viewControllerForIndex method, assign viewcontroller.view.tag = index so that each viewcontroller.view is assigned a value.

Have the currentIndex property that is initially assigned to the viewcontroller index that you created in pageviewcontroller

Now in didFinishAnimating do the following

func pageViewController (_ pageViewController: UIPageViewController, didFinishAnimating Finished: Bool, previousViewControllers: [UIViewController], transitionCompleted complete: Bool) {if! complete {return // return if the animation is not complete}, let pCont = bottomDataContainer ?? 0.ont how? CustomVC // take out the current VC

  if currentIndex < pCont?.view.tag ?? 0 { topNavView.goToNextDate() }else{ topNavView.goToPrevDate() } selectedIndex = pCont?.view.tag ?? 0 } 
0
source

Source: https://habr.com/ru/post/980951/


All Articles