13

I have a view controller set up programmatically which has a child UIPageViewController. This displays various other view controllers that are also set up programmatically. These view controllers' views have translatesAutoresizingMaskIntoConstraints set to YES, but the page view controller's view uses constraints to position itself in the top view controller.

The problem is, when the user rotates the device the page view controller resizes its frame but its child view controllers don't. By didRotateFromInterfaceOrientation, its frame is still from the old orientation. I've verified that the rotation methods are called on the child view controllers, their frame just doesn't change.

I set up the page view controller like this:

self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
self.pageViewController.view.backgroundColor = [UIColor clearColor];
self.pageViewController.view.translatesAutoresizingMaskIntoConstraints = NO;
self.pageViewController.dataSource = self;
self.pageViewController.delegate = self;
[self.pageViewController willMoveToParentViewController:self];
[self.view addSubview:self.pageViewController.view];
[self addChildViewController:self.pageViewController];
[self.pageViewController didMoveToParentViewController:self];

self.currentPageIndex = 0;

self.currentPageController = [self pageForIndex:self.currentPageIndex];
self.currentPageController.delegate = self;
[self.pageViewController setViewControllers:@[self.currentPageController] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];

I've tried calling setNeedsLayout but it's a clumsy rotation animation and the next page that I swipe to is also not resized properly.

Why is the page view controller not resizing its child view controllers, and how do I get it to do this?

Thanks!

architectpianist
  • 2,562
  • 1
  • 19
  • 27
  • Did you find a solution to your problem? I am stuck with with the same issue. – AlexR Sep 16 '13 at 08:26
  • The problem is that -didRotateFromInterfaceOrientation on the child controllers never gets called. I solved it by manually calling it from the parent view controllers -didRotateFromInterfaceOrientation. – Mani Jan 31 '14 at 12:42
  • What's the method on clild view controller are you calling to handle the orientation change? – Satyam Feb 18 '15 at 10:14
  • I have same problem, but not for rotation, its for multitasking view. If you found any solution pls share it – Johnykutty Aug 06 '15 at 09:32

2 Answers2

6

First, set up everything with auto layout, programmatically or Storyboard. Then, catch the orientation change in the parent view controller and force the UIPageViewController's view to layout again.

This is my working code (iOS 8.0 and later). childController1 was set up on a Storyboard with all layout using constraints, and instantiated with [self.storyboard instantiateViewControllerWithIdentifier:@"ChildControllerId"].

- (void)createPageController
{
...
    pageController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStyleScroll navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
    pageController.dataSource = self;
    [pageController setViewControllers:@[childController1] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:nil];
    [self addChildViewController:pageController];
    [self.view addSubview:pageController.view];
    UIView *pageView = pageController.view;
    pageView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[pageView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(pageView)]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[pageView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(pageView)]];
    [pageController didMoveToParentViewController:self];
...
}
- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    [pageController.view setNeedsLayout];
    [super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator];
}

Hope it helps.

camilomq
  • 3,021
  • 1
  • 17
  • 10
-2

Adding a controller's view directly into another controller's view and expecting the rotation and life cycle methods to be called isn't the best policy. I kind of feel adding it to the controller hierarchy could work, but I can't comment much on it.

I tested with a tab bar navigator and my UIPageViewController got the events along with the controller that was being shown in the UIPageViewController. I'm guessing that if I push the controller into a UINavigationController I'll get the same result.

I'd recommend you to show your UIPageVIewController in a more standard way than adding it's view to another controller's view.

  • Its not necessary that page view controller must be full screen always. On a device like iPad, it can be part of the view. And so it has to be implemented as mentioned in the question. Correct me if there's any other way to achieve it. – Satyam Feb 17 '15 at 13:25