57

I would like to do to a pretty simple thing. Just remove all the dots, and the bar on the bottom of the UIPageViewController.

This is the setup: I have a custom view controller which has UIPageViewController *pageController I display it like this:

self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];

self.pageController.dataSource = self;
[[self.pageController view] setFrame:[self.view bounds]];

BSItemPageViewController *initialViewController = [self viewControllerAtIndex:selectedIndex];

NSArray *viewControllers = [NSArray arrayWithObject:initialViewController];

[self.pageController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];

[self addChildViewController:self.pageController];
[[self view] addSubview:[self.pageController view]];
[self.pageController didMoveToParentViewController:self];

Any ideas on how do I remove the dots?

san
  • 3,350
  • 1
  • 28
  • 40
Stefan Salatic
  • 4,513
  • 3
  • 22
  • 30
  • That is an Apple signature feature that most users are expected to see. How would they know that they need to switch pages then. In fact that is now used by a number of websites too. As each page changes automatically the dot changes. – logixologist Dec 23 '13 at 18:15
  • I understand that, and I'm doing most of my app according to Apple guidelines, but this is just a secondary way to navigate, and there are bunch of items so I would prefer to not have dots. – Stefan Salatic Dec 23 '13 at 18:43

5 Answers5

209

The page control is only displayed if the datasource implements these methods:

presentationCountForPageViewController:
presentationIndexForPageViewController:

Simply remove your implementation of these, and the page control will not be displayed. From the datasource docs:

If both of the methods in “Supporting a Page Indicator” are implemented and the page view controller’s transition style is UIPageViewControllerTransitionStyleScroll, a page indicator is visible.

Stan James
  • 2,535
  • 1
  • 28
  • 35
jrturton
  • 118,105
  • 32
  • 252
  • 268
  • 5
    If you need voiceover to read out the page number (1 of 5, 2 of 5, etc.) then this solution doesn't work. Otherwise, it's fine. – Lee Nov 23 '15 at 15:19
  • 2
    I added a solution to address the accessibility concerns mentioned by @Lee. Essentially, just call UIPageControl.appearance().isHidden = true (Swift solution). – Daniel Sep 06 '19 at 00:46
13

In my situation I have multiple UIPageViewControllers (created from -[UITableView didSelectRowAtIndexPath]), some of which contain only 1 page. Instead of using different controllers for different UITableView rows, I implemented the UIPageViewController delegate method as follows:

- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController {
    return ([self numberOfPages] == 1 ? 0 : [self numberOfPages]);
}

This returns 0 if there is only 1 page which seems to make UIPageViewController not show the dots. It's a kludge but it appears to work (iOS SDK 7.0).

I suppose a "cleaner" way would be to remove the methods at runtime for those UIPageControllers having only 1 page, but this would involve some fancy objC runtime manipulation.

Comments on this approach?

mts
  • 608
  • 6
  • 11
  • 1
    If you want to ask a question, don't put it in an answer but start a new thread for it. The "Ask Question" button is in the top right of this page. More people would see your question and try to answer that way. – sth Mar 12 '14 at 01:39
  • 2
    @sth I appreciate your comment since I am not a frequent contributor to Stack Overflow. What is the preferred protocol here? I provided an answer to the OP's question so I assume that that part should be submitted as an answer. But I believe my question makes little sense outside of the context of the original question. Are you suggesting that I start a new thread in order to solicit comments on my approach? Perhaps I shouldn't have asked for comments? – mts Mar 13 '14 at 02:05
  • 3
    You can configure UIPageControl to automatically hide the dots if there's only a single page. In Swift: `let pageControl = UIPageControl.appearance(); pageControl.hidesForSinglePage = true`. – user2067021 Jun 06 '17 at 03:48
4

If you want to hide those dots dynamically at runtime, then return -1 from the presentationIndexForPageViewController delegate:

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

func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
    return yourPageVCs.count > 1 ? 0 : -1
}

In this case if you have only 1 (single sided) page, dots will be hidden.

iOSergey
  • 636
  • 5
  • 5
2

The above fixes works fine with fixed number of pages at the beginning.

I tried different approaches to solve the problem when pages can be increased or decreased dynamically.

So I used below method which will manually hide the component itself.

func togglePageControl(pageCount: Int, threshold: Int = 1) {

    var hidden = true

    if pageCount > threshold {

        hidden = false

    }

    for subView in self.view.subviews {
        if subView is UIScrollView {
            subView.frame = self.view.bounds
        } else if subView is UIPageControl {
            subView.isHidden = hidden
        }
    }
}

And this should be called from

public func presentationCount(for pageViewController: UIPageViewController) -> Int {

    togglePageControl(pageCount: pages.count)

    // or togglePageControl(pageCount: pages.count, threshold: 5)

    return pages.count
}
Muhammed Basil
  • 1,834
  • 1
  • 21
  • 39
2

As Lee pointed out, simply not implementing the methods presentationCountForPageViewController and presentationCountForPageViewController suffers from an accessibility issue during voiceover where it won't read out the page number (1 of 5, 2 of 5, etc.). A solution that will support accessibility is:

// Swift
let proxy = UIPageControl.appearance()
proxy.isHidden = true

// Objective-C
UIPageControl *proxy = [UIPageControl appearance];
[proxy setHidden:YES];

This has the added benefit of maintaining a cleaner separation between the data source and its presentation.

UPDATE: This is unfortunately not a perfect solution since it hides the control but doesn't remove it (there remains an empty space the same height of the hidden control). I haven't yet been able to find a way to configure the existing control to fix this issue.

Daniel
  • 461
  • 4
  • 6