Reputation: 505
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
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
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
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