1

I have four pages in a UIPageViewController, and I'd like to hide the dots on the last page. I successfully made a function that gets called on the last page of the UIPageViewController. Basically, if the current view is the last one, it is called. But what do I put in that function to hide the dots temporarily?

I found this https://stackoverflow.com/a/32016614/5700898 but it doesn't help with what goes inside that function. The normal method (hiding page dots on all pages), is not what I need.

How can I hide the page indicator dots only on the last page of a UIPageViewController?

Edit: Here's my code as asked for.

import UIKit

class TutorialController: UIPageViewController {

    let pageControl = UIPageControl.appearanceWhenContainedInInstancesOfClasses([])

    var currentview = "0"

    private func stylePageControl() {

        pageControl.currentPageIndicatorTintColor = UIColor.lightGrayColor()
        pageControl.pageIndicatorTintColor = UIColor.darkGrayColor()
        pageControl.backgroundColor = UIColor.whiteColor()
    }

    private func hidePageControl() { // this should let us hide the dots on the fourth view, by changing color.

        pageControl.backgroundColor = UIColor(red: 0.2980392157, green: 0.2980392157, blue: 0.2980392157, alpha: 1.0)
        pageControl.currentPageIndicatorTintColor = UIColor(red: 0.2980392157, green: 0.2980392157, blue: 0.2980392157, alpha: 1.0)
        pageControl.pageIndicatorTintColor = UIColor(red: 0.2980392157, green: 0.2980392157, blue: 0.2980392157, alpha: 1.0)
    }


    private(set) lazy var orderedViewControllers: [UIViewController] = {
        return [self.newViewController("1"),
                self.newViewController("2"),
                self.newViewController("3"),
                self.newViewController("4")]
    }()

    private func newViewController(number: String) -> UIViewController {
        return UIStoryboard(name: "Main", bundle: nil) .
            instantiateViewControllerWithIdentifier("Tutorial\(number)") // calls the next view controller.
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        stylePageControl() // just changing the color, this works.
        dataSource = self

        if let firstViewController = orderedViewControllers.first {
            setViewControllers([firstViewController],
                               direction: .Forward,
                               animated: true,
                               completion: nil)
        }

    }
}

// MARK: UIPageViewControllerDataSource

extension TutorialController: UIPageViewControllerDataSource {

    func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
        return orderedViewControllers.count

    }

    func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
        guard let firstViewController = viewControllers?.first,
            firstViewControllerIndex = orderedViewControllers.indexOf(firstViewController) else {
                return 0
        }

        return firstViewControllerIndex
    }


    func pageViewController(pageViewController: UIPageViewController,
                            viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = orderedViewControllers.indexOf(viewController) else {
            return nil
        }

        let previousIndex = viewControllerIndex - 1


        guard previousIndex >= 0 else {
            return nil
        }

        guard orderedViewControllers.count > previousIndex else {
            return nil
        }

        return orderedViewControllers[previousIndex]
    }

    func pageViewController(pageViewController: UIPageViewController,
                            viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = orderedViewControllers.indexOf(viewController) else {
            return nil
        }

        let nextIndex = viewControllerIndex + 1
        currentview = "\(nextIndex)"
        print("now on tutorial slide \(currentview)")
        if currentview == "4" { // this is called successfully when the fourth page comes into view.
            print("we are now on the fourth slide; hiding the page dots...") // this successfully prints.


      UIPageControl.appearanceWhenContainedInInstancesOfClasses([TutorialController.s‌​elf]).hidden = true // this should hide the all page controller dots, but it just doesn't work.
        pageControl.hidden = true // also should hide page controller dots, also doesn't work.
        hidePageControl() // this should change the color of the page controller dots, but doesn't (note that this function works to change color when I call it on viewDidLoad, but that's not where I want it; it doesn't work here).

        print(pageControl.hidden) // always prints false, even though I am trying to set it to true.

        }

        let orderedViewControllersCount = orderedViewControllers.count

        guard orderedViewControllersCount != nextIndex else {
            return nil
        }

        guard orderedViewControllersCount > nextIndex else {
            return nil
        }

        return orderedViewControllers[nextIndex]
    }

}
Community
  • 1
  • 1
owlswipe
  • 19,159
  • 9
  • 37
  • 82

5 Answers5

1

use the UIPageViewControllerDelegate method:

let pageControl = UIPageControl()

func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
    if (index == numberOfPages()-1){
          pageControl.hidden = true
    }else{
          pageControl.hidden = false
    }
}
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Eduardo Oliveros
  • 863
  • 9
  • 20
1

I found that you can't actually hide the page control as it just never works. But a bit of a hack is to add this to your code:

    func pageViewController(pageViewController: UIPageViewController, willTransitionToViewControllers pendingViewControllers: [UIViewController]) {
        if let lastVC = pendingViewControllers.last?.isKindOfClass(youLastViewController){
            if lastVC == true {
                for view in self.view.subviews {
                    if view is UIScrollView {
                        view.frame = UIScreen.mainScreen().bounds
                    } else if view is UIPageControl {
                        view.center.y = self.view.frame.height * 1.5
                    }
                }
            }else {
                for view in self.view.subviews {
                    if view is UIScrollView {
                        view.frame = UIScreen.mainScreen().bounds
                    } else if view is UIPageControl {
                        view.center.y = self.view.frame.height * 0.92
                    }
                }
            }
        }
    }
}

This actually move the page control of the screen and the same as hiding it.

Henry Brown
  • 2,219
  • 8
  • 31
  • 48
1

here is the complete code of UIPageViewController to hide dots from last page it's work fine

first create class for UIViewController and add UIPageViewControllerDelegate , UIPageViewControllerDataSource

create outlet for pageControl

@IBOutlet weak var pageControl: UIPageControl!

create variable for uipagecontroller

var pageControllerContainer : UIPageViewController!

var pages = [UIViewController]()

var currentIndex : Int?

private var pendingIndex : Int?
private var lastIndex : Int?

in ViewDidLoad: add following lines :

 let page1 : UIViewController! = self.storyboard?.instantiateViewController(withIdentifier: "YourFirstPageViewController") as! YourFirstPageViewController
    let page2 : UIViewController! = self.storyboard?.instantiateViewController(withIdentifier: "YourSecondPageViewController") as! YourSecondPageViewController
    let page3 : UIViewController! = self.storyboard?.instantiateViewController(withIdentifier: "YourThirdPageViewController") as! YourThirdPageViewController

    pages.append(page1)
    pages.append(page2)
    pages.append(page3)

    pageControllerContainer = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
    pageControllerContainer.delegate = self
    pageControllerContainer.dataSource = self
    pageControllerContainer.setViewControllers([page1], direction: .forward, animated: true, completion: nil)

    view.addSubview(pageControllerContainer.view)
    view.bringSubview(toFront: pageControl)
    pageControl.numberOfPages = pages.count
    pageControl.currentPage = 0

now create following delegates method for pageviewcontroller:

     func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {

    let currentIndex = pages.index(of: viewController)

    if currentIndex == 0
    {
        return nil
    }
    let previousIndex = abs((currentIndex! - 1) % pages.count)
    return pages[previousIndex]
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {


    let currentIndex = pages.index(of: viewController)

    if currentIndex == pages.count - 1
    {
        return nil
    }

    let nextIndex = abs((currentIndex! + 1 ) % pages.count)
    return pages[nextIndex]
}

after that create following datasource methods

    func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {

    pendingIndex = pages.index(of: pendingViewControllers.first!)

}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {

    if completed
    {

        currentIndex = pendingIndex
        if let index = currentIndex
        {
            pageControl.currentPage = index
        }
    }
     lastIndex = pages.count - 1
      print(lastIndex as Any)
      print(currentIndex as Any)

    if currentIndex == lastIndex
    {
        pageControl.isHidden = true
    }
    else
    {
        pageControl.isHidden = false
    }
}

this will allows to hide page controller when it comes to last index means last page

hope this will help :-) thank you ...

Viral Shah
  • 89
  • 1
  • 3
  • 10
0
override func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
    if /*current index is the last one*/ {
        return 0
    } else {
        /*return number of pages*/
    }
}
Artem Deviatov
  • 970
  • 12
  • 20
0

Check out the accepted answer here to get the UIPageControl (the view with the dots):

Access the UIPageControl created by iOS6 UIPageViewController?

Then, once you have the pageControl, in pageViewController: didFinishAnimating: you can check if it's the last page, and if so set pageControl.hidden = true.

Community
  • 1
  • 1
Hash88
  • 692
  • 1
  • 6
  • 17
  • So I'm really close: I have the function that's successfully called when it's the last page. In that function, I have `pageControl.hidden = true`. So that should work! But it doesn't, because for some reason pageControl does not hide. Even printing `print(pageControl.hidden)` returns false. So what's going on here? – owlswipe Apr 03 '16 at 22:34
  • Hmm. Maybe you're not getting the right page control. Do you have more than one page control around? You can also try `UIPageControl.appearanceWhenContainedInInstancesOfClasses([MyClass.self]).hidden = true`. That will affect all instances of UIPageControl that are inside of whatever class you specify. – Hash88 Apr 03 '16 at 22:39
  • I tried this but no dice still: `UIPageControl.appearanceWhenContainedInInstancesOfClasses([TutorialController.self]).hidden = true` – owlswipe Apr 03 '16 at 23:26
  • Also, one note: I'm doing all this inside the main UIPageViewController that controls all four pages and their paging, not inside the any of the particular views. – owlswipe Apr 03 '16 at 23:27
  • Can you paste your code so I can get a closer look? – Hash88 Apr 03 '16 at 23:29
  • I pasted my code, note that the important stuff is mostly towards the end. – owlswipe Apr 03 '16 at 23:50
  • Your code looks right, not sure what's the issue. I've found that doing stuff with a UIPageViewController's UIPageControl is tricky. Unfortunately, Apple doesn't give devs very much control over it. You can alway try rolling your own UIPageControl instance and mange it inside the page controller delegate/data source methods. – Hash88 Apr 04 '16 at 00:09
  • Did you ever sort this? I'm having the same problem. – Henry Brown Aug 17 '16 at 13:40
  • @HenryBrown I actually never did! Artyom's and Hash88's code never worked for me, but I haven't tried the latest answer from Eduardo down below. And I'm away from my computer for a few days! So if you could try it and report back, that would be great. Good luck ;). – owlswipe Aug 18 '16 at 15:43