I'm presenting a UIViewController using presentViewController and a custom modalPresentationStyle, in an effort to implement a Facebook POP animated transition.
The modal view itself is completely dynamic, defined using Autolayout constraints in code. There is no xib/storyboard to back the modal.
I can't get the modal view to center on screen. Autolayout isn't sufficient, because there is no superview to add constraints on.
My presenting code looks like this (taken from a FB POP code sample):
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
UIView *fromView = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey].view;
fromView.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed;
fromView.userInteractionEnabled = NO;
UIView *dimmingView = [[UIView alloc] initWithFrame:fromView.bounds];
dimmingView.backgroundColor = [UIColor colorWithRed:(24/255.0) green:(42/255.0) blue:(15/255.0) alpha:1.0];
dimmingView.layer.opacity = 0.0;
UIView *toView = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey].view;
toView.frame = CGRectMake(0,
0,
CGRectGetWidth(transitionContext.containerView.bounds) - 104.f,
CGRectGetHeight(transitionContext.containerView.bounds) - 320.f);
toView.center = CGPointMake(transitionContext.containerView.center.x, -transitionContext.containerView.center.y);
[transitionContext.containerView addSubview:dimmingView];
[transitionContext.containerView addSubview:toView];
POPSpringAnimation *positionAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionY];
positionAnimation.toValue = @(transitionContext.containerView.center.y);
positionAnimation.springBounciness = 10;
[positionAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
[transitionContext completeTransition:YES];
}];
POPSpringAnimation *scaleAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerScaleXY];
scaleAnimation.springBounciness = 20;
scaleAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(1.2, 1.4)];
POPBasicAnimation *opacityAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPLayerOpacity];
opacityAnimation.toValue = @(0.2);
[toView.layer pop_addAnimation:positionAnimation forKey:@"positionAnimation"];
[toView.layer pop_addAnimation:scaleAnimation forKey:@"scaleAnimation"];
[dimmingView.layer pop_addAnimation:opacityAnimation forKey:@"opacityAnimation"];
}
This works beautifully, but I need the actual view size to be dynamic (sometimes the modal will have four lines of text and two buttons, etc). To accomplish this, I need to set translatesAutoresizingMaskIntoConstraints=NO in the VC subclass. This obviously negates the frame centering I'm doing in the presentation animator.
The end result is a modal that's stuck to the left edge of the screen; it centers itself vertically but not horizontally. Visually it looks something like this (don't mind the black squares):
The obvious solution would be to add a view constraint that centers the view.
But where do I add it? view.superview is nil; there is no superview. I tried creating a custom 'superview' property and setting it, but autolayout doesn't know how to handle a view that's outside of its view hierarchy (the presenting vc). This is what my view hierarchy looks like, annotated:
Apparently I'm not supposed to access the UITransitionView directly. Constraints on the UIWindow have no effect.
Does anyone have any advice? How do you guys handle this sort of thing?