Group Group Group Group Group Group Group Group Group

UIPageViewController & UIPageControl: Rotation problems

#1

The app I’m currently working on has a UIPageViewController that has 3 ViewControllers.

I’m scrolling through these fine. No problems - either in portrait OR landscape.

I added a UIPageControl to the UIPageViewController, in code - not in the Storyboard, and as such, in portrait mode, I have a nice sequence of dots that show the scroll position through my paged ViewControllers.

That all works great.

EXCEPT, when I rotate into landscape.

When in landscape the UIPageViewController and the 3 ViewControllers work perfectly; scrolling and showing content and are interactive.

However the UIPageControl indicator as ‘vanished’.

Now, I will preface this with the fact that my UIPageViewController is part of a larger UITabBarViewController project, and as such at the bottom of the screen is a Tab Bar.

But when in portrait, I specifically positioned the UIPageControl (in code) to be ‘above’ that tab bar, and it is, and it displays, but it’s totally gone in landscape.

Can anyone PLEASE help me?

This is the code I used to ‘add’ the UIPageControl:

private func configurePageControl()
{
    self.pageControl = UIPageControl(frame: CGRect(x: 0, y: UIScreen.main.bounds.maxY - 90, width: UIScreen.main.bounds.width, height: 50))
    
    self.pageControl.numberOfPages = orderedViewControllers.count
    self.pageControl.currentPage = 0
    self.pageControl.tintColor = UIColor.white
    self.pageControl.pageIndicatorTintColor = UIColor.black
    self.pageControl.currentPageIndicatorTintColor = UIColor.white
    self.view.addSubview(self.pageControl)
}

And that code is in the UIPageViewController where nothing but the handling of the 3 separate view controllers lives.

Thanks.

#2

That line is setting the frame of the pageControl, using the maxY and width of portrait view. It has no contraints that tie it to the container. When you go to landscape, it will still have the Y value of maxY-90 taken from portrait, which is well off the bottom of the screen in landscape.

Assuming you are adjusting your other views when it flips to landscape, you should also set the frame of the pageControl. Just set it to a new frame with the same expressions; it will use the new screen size for the values.

self.pageControl.frame = CGRect(x: 0, y: UIScreen.main.bounds.maxY - 90, width: UIScreen.main.bounds.width, height: 50)

#3

@sgerrard

Thank you; I thought it was something like that, but whereas I used to change the position on the callback to orientation changed method - which as been deprecated - I didn’t know how to fix it.

This fixed it though:

private func configurePageControl()
{
    self.pageControl.numberOfPages = orderedViewControllers.count
    self.pageControl.currentPage = 0
    self.pageControl.tintColor = UIColor.white
    self.pageControl.pageIndicatorTintColor = UIColor.black
    self.pageControl.currentPageIndicatorTintColor = UIColor.white
    self.view.addSubview(self.pageControl)

    self.pageControl.translatesAutoresizingMaskIntoConstraints = false
    let horizontalConstraint = self.pageControl.centerXAnchor.constraint(equalTo: view.centerXAnchor)
    let verticalConstraint = self.pageControl.centerYAnchor.constraint(equalTo: view.bottomAnchor, constant: -20.0)
    let widthConstraint = self.pageControl.widthAnchor.constraint(equalToConstant: 100)
    let heightConstraint = self.pageControl.heightAnchor.constraint(equalToConstant: 50)
    self.view.addConstraints([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])
}
1 Like
#4

I think adding constraints is even better.
That is the “preferred” way now. :slight_smile: