Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flickering during custom view controller transition iOS 7

I'm trying to do a very simple transition: one view moves half the screen to the left while the second ("to") view moves in half a screen.

I have the animation working, but when I reverse the animation, I see a flickering. The "to" view (i.e. the original view) is visible at the origin of 0,0 although I set a different frame.

I dumped the view hierarchy. The frames are set correctly (-100 0; 320 480 for the to view), but nonetheless it shows up at 0,0. Is a screenshot of the view cached somewhere for the animation?

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController   = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];

UIView *container = [transitionContext containerView];

CGRect offsetCoverRect    = CGRectMake(-100.0, 0.0, 320, 480);
CGRect detailsRect        = CGRectMake(-100.0 + 320.0, 0.0, 320, 480);
CGRect detailsOutsideRect = CGRectMake(320.0, 0.0, 320, 480);

CGRect normalRect = CGRectMake(0.0, 0.0, 320, 480);


if (self.revealDetails)
{
    toViewController.view.frame = detailsOutsideRect;
    [container addSubview:toViewController.view];
}
else
{
    [container insertSubview:toViewController.view belowSubview:fromViewController.view];

    // reversing… set the frame to the original offset (shows at 0,0 for a moment)
    toViewController.view.frame = offsetCoverRect;
}

[UIView animateKeyframesWithDuration:2 delay:0 options:0 animations:^{

    if (self.revealDetails)
    {
        fromViewController.view.frame = offsetCoverRect;
        toViewController.view.frame = detailsRect;
    }
    else
    {
        fromViewController.view.frame = detailsOutsideRect;
        toViewController.view.frame = normalRect;
    }
} completion:^(BOOL finished) { [transitionContext completeTransition:finished]; }];
}

Update:

It seems to be related to UIModalPresentationCustom. I need to use this so that the from view is not removed when the transition completes. However, it seems to assume that the from view controller for the reverse transition starts at 0,0.

Update 2:

Very easy to reproduce with the following code:

UIView *snapshot = [containerView snapshotViewAfterScreenUpdates:NO];
[containerView addSubview:snapshot];

The above will show the to view centered on screen, no matter what actual frame or center I set before the animation.

like image 902
Mark Avatar asked Dec 11 '13 17:12

Mark


1 Answers

I know this is an old question, but I ran into the same problem and after hours of struggling, finally came up with a solution:

In the completion block of the present animation,

  1. Create a snapshot of the fromViewController view
  2. Perform frame changes/transforms on the snapshot
  3. Add snapshot to the containerView
  4. Remove the fromViewController view from the container view
  5. In the completion block of the dismiss animation (or anywhere if its a dismiss?), remove the snapshot from the container

By removing the fromViewController's view from the container view, it does not get reset to it's initial position because it is no longer inside of the container view.

like image 155
Brad Avatar answered Oct 08 '22 01:10

Brad