juelizabeth
juelizabeth

Reputation: 505

uipageviewcontroller disable right swipe

I have a uipageviewcontroller with four individual view controllers in it. I want to disable the right swipe action for the first view controller and disable the left swipe action for the fourth view controller. When the app launches, I want the user to only be able to swipe left and not right, because swiping right, takes the user to the fourth view controller and swiping left on the fourth view controller takes the user to the first view controller. Here is my code.

class TutorialPageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
    weak var tutorialDelegate: TutorialPageViewControllerDelegate?

    lazy var VCArr: [UIViewController] = {
        return [self.VCInstance(name: "FirstVC"),
                self.VCInstance(name: "SecondVC"),
                self.VCInstance(name: "ThirdVC"),
                self.VCInstance(name: "FourthVC")]

    }()

    private func VCInstance(name: String) -> UIViewController {
        return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: name)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        let pageControl = UIPageControl.appearance()
        //Customizing
        pageControl.pageIndicatorTintColor = UIColor.lightGray
        pageControl.currentPageIndicatorTintColor = UIColor(red:0.23, green:0.73, blue:1.00, alpha:1.0)

        dataSource = self
        delegate = self
        self.dataSource = self
        self.delegate = self

        if let FirstVC = VCArr.first {
            setViewControllers([FirstVC], direction: .forward, animated: true, completion: nil)
            tutorialDelegate?.tutorialPageViewController(tutorialPageViewController: self, didUpdatePageCount: VCArr.count)

        }
    }

   override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        for view in self.view.subviews {
            if view is UIScrollView {
                view.frame = UIScreen.main.bounds
            } else if view is UIPageControl {
                view.backgroundColor = UIColor.clear
            }
        }
    }

    public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = VCArr.index(of: viewController) else {
            return nil
        }

        let previousIndex = viewControllerIndex - 1

        guard previousIndex >= 0 else {
            return VCArr.last
        }

        guard VCArr.count > previousIndex else {
            return nil
        }
        return VCArr[previousIndex]
    }

    public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = VCArr.index(of: viewController) else {
            return nil
        }

        let nextIndex = viewControllerIndex + 1

        guard nextIndex < VCArr.count else {
            return VCArr.first
        }

        guard VCArr.count > nextIndex else {
            return nil
        }
        return VCArr[nextIndex]
    }

    public func presentationCount(for pageViewController: UIPageViewController) -> Int {
        return VCArr.count
    }


    public func presentationIndex(for pageViewController: UIPageViewController) -> Int {
        guard let firstViewController = viewControllers?.first,
        let firstViewControllerIndex = VCArr.index(of: firstViewController) else {
             return 0
         }
         return firstViewControllerIndex
     }
}

extension TutorialPageViewController {

    func pageViewController(pageViewController: UIPageViewController,
                            didFinishAnimating finished: Bool,
                            previousViewControllers: [UIViewController],
                            transitionCompleted completed: Bool) {
        if let firstViewController = viewControllers?.first,
            let index = VCArr.index(of: firstViewController) {
            tutorialDelegate?.tutorialPageViewController(tutorialPageViewController: self, didUpdatePageIndex: index)
        }
    }

}

Upvotes: 2

Views: 4507

Answers (3)

Arsienij
Arsienij

Reputation: 167

  for view in self.view.subviews  {
    if let view = view as? UIScrollView {
      view.bounces = true
    }
  }

This code really helps me to hide white spaces, so we can't swipe after the last (very left) or before first screen (very right).

.isScrollEnabled = false

And this code doesn't really help, because it totally blocked swiping between pages.

Upvotes: 0

Mohsen Fard
Mohsen Fard

Reputation: 596

You can use this extension for disable all direction swipe :

extension UIPageViewController {
     var isPagingEnabled: Bool {
        get {
           var isEnabled: Bool = true
           for view in view.subviews {
               if let subView = view as? UIScrollView {
                   isEnabled = subView.isScrollEnabled
               }
           }
           return isEnabled
       }
       set {
           for view in view.subviews {
               if let subView = view as? UIScrollView {
                   subView.isScrollEnabled = newValue
               }
           }
       }
   }    
}

and call this:

pageCtrl.isPagingEnabled = false

Upvotes: 1

Jasmeet Kaur
Jasmeet Kaur

Reputation: 1568

Basically you need to change following lines

guard previousIndex >= 0 else {
            return nil
        }


guard nextIndex < VCArr.count else {
            return nil
        }

----- OR -----

Change viewControllerAfter as

 public func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
            guard let viewControllerIndex = VCArr.index(of: viewController) else {
                return nil
            }

            let nextIndex = viewControllerIndex + 1

            guard nextIndex < VCArr.count else {
            return nil
        }

            guard VCArr.count > nextIndex else {
                return nil
            }

            return VCArr[nextIndex]
        }

Change ViewControllerBefore as

public func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = VCArr.index(of: viewController) else {
            return nil
        }

        let previousIndex = viewControllerIndex - 1

       guard previousIndex >= 0 else {
            return nil
        }
        guard VCArr.count > previousIndex else {
            return nil
        }
        return VCArr[previousIndex]
    }

Upvotes: 2

Related Questions