Skip to content

Instantly share code, notes, and snippets.

@bcbroom
Created March 28, 2016 03:03
Show Gist options
  • Select an option

  • Save bcbroom/215e09ae026b1eb6adda to your computer and use it in GitHub Desktop.

Select an option

Save bcbroom/215e09ae026b1eb6adda to your computer and use it in GitHub Desktop.
Custom view controller transition without alignment jump
// from animator.m
- (void)animatePush:(id<UIViewControllerContextTransitioning>)transitionContext {
// seems that all the steps here have specific orders
// add toVC to container view
// auto layout step on toVC after toVC added to container
// get image frames after AL step
// have to set toVC frame offscreen after grab final image frames
// backdrop view added to container, needs to be under toVC.view
// can you add toVC to container, then set the frame later?
// if so, don't have to split toVC section of set frame/add to container, then reset frame at end
PhotoCollectionViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
PhotoDetailViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *container = [transitionContext containerView];
toVC.view.alpha = 0.0;
CGRect finalFrame = [transitionContext finalFrameForViewController:toVC];
// seems to be ok if you don't set toVC's frame - because its already set?
//toVC.view.frame = finalFrame;
// adding toVC after AL pass seemed to cause placeholder image to end up at top of screen,
// underneath the nav bar, causing a visual jump
[container addSubview:toVC.view];
// need an AL pass, or won't be setup correctly on phone sizes not designed in IB
// I would expect that you get the view after its AL pass
[toVC.view setNeedsLayout];
[toVC.view layoutIfNeeded];
UIImageView *fromImageView = [self getCellImageView:fromVC];
UIImageView *toImageView = toVC.photoImageView;
CGRect fromImageViewFrame = fromImageView.frame;
CGRect fromImageViewFrameConverted = [container convertRect:fromImageViewFrame fromView:fromImageView];
CGRect toImageFrame = toImageView.frame;
// converting to toImageView frame to container coordinates ends up with an image that is
// too low, by the height of the nav bar. It seems like its double counting the nav bar
// CGRect toImageFrameConverted = [container convertRect:toImageFrame fromView:toImageView];
UIView *placeholder = [fromImageView snapshotViewAfterScreenUpdates:NO];
placeholder.frame = fromImageViewFrameConverted;
fromImageView.hidden = YES;
toImageView.hidden = YES;
[container addSubview:placeholder];
// now move inital frame position fro toVC
// doing before messes up toImageFrame calc
CGRect frame = finalFrame;
frame.origin.y += frame.size.height;
toVC.view.frame = frame;
// backdrop view swap to get rid of "curtain" effect
UIView *backdrop = [[UIView alloc] initWithFrame:finalFrame];
backdrop.backgroundColor = toVC.view.backgroundColor;
backdrop.alpha = 0;
toVC.view.backgroundColor = [UIColor clearColor];
[container insertSubview:backdrop belowSubview:toVC.view];
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
toVC.view.alpha = 1.0;
backdrop.alpha = 1.0;
toVC.view.frame = finalFrame;
// use the unconverted image frame for the placeholder final position
placeholder.frame = toImageFrame;
} completion:^(BOOL finished) {
fromImageView.hidden = NO;
toImageView.hidden = NO;
[placeholder removeFromSuperview];
toVC.view.backgroundColor = backdrop.backgroundColor;
[backdrop removeFromSuperview];
[transitionContext completeTransition:finished];
}];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment