Search code examples
iosios7uipageviewcontroller

UIPageViewController views jump when resizing superview after swiping


I have a view controller which adds a UIPageViewController to a subview (let's call it "overlay") programmatically. Since the page view controller's pages each have a different height, I added an NSLayoutConstraint on the "overlay" subview.

On every swipe I calculate the height of the upcoming view controller and resize the overlay view accordingly:

- (void)resizeOverlayToBottomOf:(UIView *)element {

   // resize overlay in parent view controller so it shows the element
   float bottomOfElement = element.frame.origin.y + element.frame.size.height + 20;
   [self.parentViewController.overlayHeightConstraint setConstant:bottomOfElement];

   [self.parentViewController.overlayView setNeedsUpdateConstraints];
   [self.parentViewController.overlayView setNeedsLayout];
   [self.parentViewController.overlayView layoutIfNeeded];
}

Everything works as expected... until I want to change the overlay size with an animation.
I wrapped the last two lines of the above method with an animation block:

[UIView animateWithDuration:0.25f animations:^{
   [self.parentViewController.overlayView setNeedsLayout];
   [self.parentViewController.overlayView layoutIfNeeded];
}];

Now after a swipe completes, the height of the overlay view changes with an animation.

The Problem is that while the animation plays, the page view controller's content snaps back to some place off screen and swipes back in. I tried adding constraints to ensure a fixed width of the page view controller content, but nothing seems to do the trick.

Any hint on how to animate the parent view without affecting the page view controller views will be highly appreciated!


Solution

  • Well, this bit of code did the trick:

    [UIView animateWithDuration:0.25f animations:^{
        // [self.parentViewController.overlayView setNeedsLayout];
        // [self.parentViewController.overlayView layoutIfNeeded];
        CGRect frame = self.parentViewController.overlayView.frame;
        frame.size.height = bottomOfElement;
        self.parentViewController.overlayView.frame = frame;
    }];
    

    The funny thing is, it does not seem to matter what value I use for frame.size.height, the constraint seems to be put in currently anyway.

    If someone could explain why this works, I'd be delighted.