These two methods viewControllerBeforeViewController
and viewControllerAfterViewController
of the UIPageViewControllerDataSource
don't tell the direction of the swipe.
The method transitionCompleted
of the UIPageViewController
delegate doesn't help us much either. It just tells if the page was fully swiped.
So what method should I use to detect exactly the user direction (left or right)?
Probably these two properties may help:
let directionForward = UIPageViewControllerNavigationDirection.Forward
let directionReverse = UIPageViewControllerNavigationDirection.Reverse
My code looks like this:
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?
}
You should use both the willTransitionToViewControllers:
and the didFinishAnimating:
delegate methods to work out whether the transition is forward or backward. Declare a couple of index variables at the start of your class, say currentIndex
and nextIndex
(both Int
).
In the willTransitionToViewControllers
method, set the nextIndex
equal to the itemIndex
of the pending view 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
You can work out at this point whether the transition will be forward or backward: if nextIndex
> currentIndex
, then forward; if nextIndex
< currentIndex
then backward. Then in didFinishAnimating
, if completed
is true (so it completed the transition to the next view controller), set currentIndex
equal to nextIndex
so you can use currentIndex
wherever you need to indicate which page is currently on 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 the pageViewController (instance of UIPageViewController), not pageItemController
which you have in your current code.
Finally, just to note: that enum you refer to (UIPageViewControllerNavigationDirection
) is used only in the setViewControllers(_, direction:)
method.
END EDIT
For my case, I was able to determine the swiping direction by using func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [AnyObject], transitionCompleted completed: Bool)
only.
Here is how. Assume that you already have a way to reference the current index named currentIndex
. In the above method, you already have the information about the previousViewControllers
so that you can get the previous index named previousIndex
.
Basically, here is the 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
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With