How do I make the bottom bar with dots of a UIPageViewController translucent?
The same effect can be achieved simply by subclassing UIPageViewController and overriding viewDidLayoutSubviews as follows:
-(void)viewDidLayoutSubviews {
UIView* v = self.view;
NSArray* subviews = v.subviews;
// Confirm that the view has the exact expected structure.
// If you add any custom subviews, you will want to remove this check.
if( [subviews count] == 2 ) {
UIScrollView* sv = nil;
UIPageControl* pc = nil;
for( UIView* t in subviews ) {
if( [t isKindOfClass:[UIScrollView class]] ) {
sv = (UIScrollView*)t;
} else if( [t isKindOfClass:[UIPageControl class]] ) {
pc = (UIPageControl*)t;
}
}
if( sv != nil && pc != nil ) {
// expand scroll view to fit entire view
sv.frame = v.bounds;
// put page control in front
[v bringSubviewToFront:pc];
}
}
[super viewDidLayoutSubviews];
}
Then there is no need to maintain a separate UIPageControl and such.
It is very easy to make it work. You just only have to make the pageviewcontroller taller, and place a PageControl into the XIB file. The trick is put the PageControl in the foreground (and all the other common controls) at the beginning, and update the content of the PageControl with the PageViewController. Here is the code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageController.dataSource = self;
// We need to cover all the control by making the frame taller (+ 37)
[[self.pageController view] setFrame:CGRectMake(0, 0, [[self view] bounds].size.width, [[self view] bounds].size.height + 37)];
TutorialPageViewController *initialViewController = [self viewControllerAtIndex:0];
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];
// Bring the common controls to the foreground (they were hidden since the frame is taller)
[self.view bringSubviewToFront:self.pcDots];
[self.view bringSubviewToFront:self.btnSkip];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
NSUInteger index = [(TutorialPageViewController *)viewController index];
[self.pcDots setCurrentPage:index];
if (index == 0) {
return nil;
}
index--;
return [self viewControllerAtIndex:index];
}
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController {
NSUInteger index = [(TutorialPageViewController *)viewController index];
[self.pcDots setCurrentPage:index];
index++;
if (index == 3) {
return nil;
}
return [self viewControllerAtIndex:index];
}
- (TutorialPageViewController *)viewControllerAtIndex:(NSUInteger)index {
TutorialPageViewController *childViewController = [[TutorialPageViewController alloc] initWithNibName:@"TutorialPageViewController" bundle:nil];
childViewController.index = index;
return childViewController;
}
- (NSInteger)presentationCountForPageViewController:(UIPageViewController *)pageViewController {
// The number of items reflected in the page indicator.
NSInteger tutorialSteps = 3;
[self.pcDots setNumberOfPages:tutorialSteps];
return tutorialSteps;
}
- (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController {
// The selected item reflected in the page indicator.
return 0;
}
Swift 3 snippet
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if let scrollView = view.subviews.filter({ $0 is UIScrollView }).first,
let pageControl = view.subviews.filter({ $0 is UIPageControl }).first {
scrollView.frame = view.bounds
view.bringSubview(toFront:pageControl)
}
}