How to animate appearance of a child in a custom container view controller

Hi all,


I'm using a custom view controller which allows to add (show) child view controllers. Currently I'm using the following scheme to add a view controller:


- (void)addViewController:(UIViewController*)viewController
{
    [self addChildViewController:viewController];
    viewController.view.frame = [self _startFrameFor:viewController];
    [self.view addSubview:viewController.view];

    [UIView animateWithDuration:ANIMATION_DURATION
                     animations:^{
                         viewController.view.frame = [self _endFrameFor:viewController];
                     } completion:^(BOOL finished) {
                         [viewController didMoveToParentViewController:self];
                     }];
}


This did it's job until iPhone X and its safeAreaInsets came into play.


If, for example, the iPhone X is in landscape mode and I add a view controller to the left of the container view controller, the view (e.g. a UITableViewController) is moved in without respecting any safeAreaInsets. After viewDidAppear being called, the view relayouts with the correct safeAreaInsets.


Just out of curiosity I checked what happens when I show the child view controller with a cutsom presentation. So I setup this very simple animator:


- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    UIView* containerView = transitionContext.containerView;
    UIView* toView = [transitionContext viewForKey:UITransitionContextToViewKey];

    toView.frame = self.sourceFrame;
    [containerView addSubview:toView];
    [UIView animateWithDuration:ANIMATION_DURATION
                     animations:^{
                         toView.frame = self.targetFrame;
                     } completion:^(BOOL finished) {
                         [transitionContext completeTransition:finished];
                     }];
}


and presented the child view controller with a

modalPresentationStyle
=
UIModalPresentationCustom
. This way the child view controller is animated in already respecting any safeAreaInstes. But of course I don't want to modally present the view controller.


Any idea how to correctly animate adding or removing a child view controller to / from a custom container view controller.


Dirk.

Hi just.do.it


Safe area insets are updated during the layout pass. Try forcing a layout on the view you just added before calling -animateWithDuration:animations:completion: to animate the view into its final position.


[viewController.view setNeedsLayout]

[viewController.view layoutIfNeeded]


You might also try calling -animateWithDuration:delay:options:animations:completion: instead, passing UIViewAnimationOptionLayoutSubviews to the options argument. I have not tested this approach myself.

That seems to work. Thank you for helping me out.


Any idea how to get the same result using a UIDynamicAnimator? That's my initial problem. :-) I've changed the container view controller to plain UIView animation to see if I can get it working this way. Which I did with your help. 😀


But originally the container view controller uses a UIDynamicAnimator with some UIGravityBehavior and some UICollisionBehavior to animated the view in place. That works quite well besides the safeAreaInsets problem. 🙂


Dirk

How to animate appearance of a child in a custom container view controller
 
 
Q