UIViewController – issue with custom dismiss transition

后端 未结 2 1465
名媛妹妹
名媛妹妹 2020-12-23 14:41

Summary

I have a content UIViewController that presents a settings UIViewController using a custom transition. The presentation is with presentViewController

相关标签:
2条回答
  • 2020-12-23 15:14

    A few potential gotchas with dismissal of modally presented view controllers using custom transition animations:

    • Add the presented ("to") view to the container, then bring the presented view front. Don't add the presenting view as you might remove it from its current superview.
    • On dismiss, UIKit sets the alpha of the presented view to 0 before animateTransition is called. So you'll want to set it to 1.0 or whatever it was at the completion of the present before firing off your dismiss animation(s).
    • Likewise for the presented view's transform. On dismiss it gets reset to identity before your animateTransition is called.

    Given all that, I think this should work:

    -(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
    {
        UIViewController *fromController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        UIViewController *toController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
        UIView *containerView = transitionContext.containerView;
        
        const BOOL isUnwinding = [toController presentedViewController] == fromController;
        const BOOL isPresenting = !isUnwinding;
        
        UIViewController *presentingController = isPresenting ? fromController : toController;
        UIViewController *presentedController = isPresenting ? toController : fromController;
        
        [containerView addSubview:presentingController.view];
        [containerView bringSubviewToFront:presentingController.view];
        
        if(isPresenting)
        {
            // Set up the initial position of the presented settings controller. Scale it down so it seems in the distance. Alpha it down so it is dark and shadowed.
            presentedController.view.transform = CGAffineTransformMakeScale(0.9, 0.9);
            presentedController.view.alpha = 0.7;
            
            [UIView animateWithDuration: [self transitionDuration: transitionContext] animations:^{
                // Lift up the presented controller.
                presentedController.view.transform = CGAffineTransformMakeScale(1.0, 1.0);
                
                // Brighten the presented controller (out of shadow).
                presentedController.view.alpha = 1;
                
                // Push the presenting controller down the screen – 3d effect to be added later.
                presentingController.view.layer.transform = CATransform3DMakeTranslation(0,400,0);
            } completion: ^(BOOL finished){
                [transitionContext completeTransition: ![transitionContext transitionWasCancelled]];
            }];
        }
        else
        {
            presentedController.view.transform = CGAffineTransformMakeScale(0.9, 0.9);
            presentedController.view.alpha = 0.7;
            
            [UIView animateWithDuration: [self transitionDuration: transitionContext] animations:^{
                // Bring the presenting controller back to its original position.
                presentingController.view.layer.transform = CATransform3DIdentity;
                
                // Lower the presented controller again and put it back in to shade.
                presentedController.view.transform = CGAffineTransformMakeScale(0.9, 0.9);
                presentedController.view.alpha = 0.4;
            } completion:^(BOOL finished) {
                [transitionContext completeTransition: ![transitionContext transitionWasCancelled]];
            }];
        }
    }
    
    0 讨论(0)
  • 2020-12-23 15:20

    Initially, I thought about using CATransition to have custom transition effect when presentViewController:animated:completion: and dismissViewControllerAnimated:completion: a View Controller. But you want to show a portion of View Controller when the setting View Controller is presented, then I think CATransition would not help because you don't have full control of how far you want to move the View Controller.

    I think the easiest way is to have one single View Controller with two full screen UIView. For the first UIView (View Controller's view, that is, self.view), you layout the setting, and on the second UIView, it's the regular View. In the ViewDidLoad, you add the 2nd view by using [self.view addSubview:2ndView];. Later when you want to present the setting view, you can do

    CGRect frame = secondView.frame;
    frame.origin.y = the_y_coordinate_you_like;
    UIView animateWithDuration:0.2 animations:^{
        secondView.frame = frame;
    }];
    

    then do the other way to bring the 2ndView back.

    0 讨论(0)
提交回复
热议问题