Septiadi Agus Septiadi Agus - 1 year ago 105
Objective-C Question

Can we customize the page indicator in UIPageViewController?

Now it's white dots with black background. What about if I want it to be black dots with white backgrounds?

- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController NS_AVAILABLE_IOS(6_0)
return _imageArrays.count;
}// The number of items reflected in the page indicator.
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController NS_AVAILABLE_IOS(6_0)
return self.intCurrentIndex;
}// The selected item reflected in the page indicator.


I don't believe that you can manipulate the UIPageViewController's page control. My solution:

I have a "root" UIViewController that is UIPageViewControllerDelegate and UIPageViewControllerDataSource.

On this root view controller, I have @property (strong, nonatomic) IBOutlet UIPageControl *pageControl. In the corresponding storyboard nib, I add a UIPageControl, position it, and check "Hides for Single Page". I can also change the colors, if I wish.

Then, I add the following in the root view controller's viewDidLoad: self.pageControl.numberOfPages = [self.features count]

My root view controller also has @property (strong, nonatomic) UIPageViewController *pageViewController. And in the implementation:

self.pageViewController = [[UIPageViewController alloc]

self.pageViewController.delegate = self;
DataViewController *startingViewController = [self viewControllerAtIndex:0 storyboard:self.storyboard];
NSArray *viewControllers = @[startingViewController];
[self.pageViewController setViewControllers:viewControllers
self.pageViewController.dataSource = self;      
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
self.pageViewController.view.frame = CGRectMake(0.0, 0.0, [[UIScreen mainScreen] bounds].size.width, [[UIScreen mainScreen] bounds].size.height + 10.0);
[self.pageViewController didMoveToParentViewController:self];
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;

(SIDE NOTE: That line that sets the frame makes the height of the UIPageViewController's view exceed the screen size so that the native page control is no longer visible. My app is portrait only, iPhone only, so I got off a bit easy here. If you need to handle rotations, you'll have to find a way to keep that native page control offscreen. I tried using auto layout, but UIPageViewController creates a set of magic views that have a bunch of autolayout mask constraints that I couldn't find a way to override.)

Anyway...then I add an extra UIPageViewController delegate method to change my new, non-native UIPageControl to the currently-selected page:

- (void)pageViewController:(UIPageViewController *)viewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed
  if (!completed){return;}

  // Find index of current page
  DataViewController *currentViewController = (DataViewController *)[self.pageViewController.viewControllers lastObject];
  NSUInteger indexOfCurrentPage = [self indexOfViewController:currentViewController];
  self.pageControl.currentPage = indexOfCurrentPage;

Not as pretty as I would like, but Apple's API for this class doesn't exactly lend itself to elegance.