Workaround for custom UIViewController animations in landscape?

后端 未结 5 915
逝去的感伤
逝去的感伤 2021-01-31 05:34

I have a custom animated UIViewController transition, and it seems that there is a bug in iOS that screws up the layout in landscape orientation. In the main animation method, i

5条回答
  •  爱一瞬间的悲伤
    2021-01-31 06:11

    I came across this issue and I just don't feel that the above solutions do this any justice. I propose a solution that doesn't require hacky code and hard coded frames.

    UIView has an awesome function to convert a CGRect into the coordinate space of another (namely; +[UIView convertRect:fromView:]). So I want to detail a far simpler way one can achieve this effect in any orientation without any hardcoded values. In this example lets say we want a simple animation that slides a view in from the right of the screen.

    So in our animator's animateTransition(:) we could simply perform the following:

    Swift

    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
        let toViewController = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
        let fromViewController = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
        
        let toView = toViewController.view
        let fromView = fromViewController.view
        let containerView = transitionContext.containerView()
        
        if(isPresenting) {
            //now we want to slide in from the right
            let startingRect = CGRectOffset(fromView.bounds, CGRectGetWidth(fromView.bounds), 0)
            toView.frame = containerView.convertRect(startingRect, fromView:fromView);
            containerView.addSubview(toView)
            let destinationRect = containerView.convertRect(fromView.bounds, fromView: fromView)
            UIView.animateWithDuration(transitionDuration(transitionContext),
                delay: 0,
                usingSpringWithDamping: 0.7,
                initialSpringVelocity: 0.7,
                options: .BeginFromCurrentState,
                animations: { () -> Void in
                    toView.frame = destinationRect
            }, completion: { (complete) -> Void in
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
            })
        } else {
            //we want to slide out to the right
            let endingRect = containerView.convertRect(CGRectOffset(fromView.bounds, CGRectGetWidth(fromView.bounds), 0), fromView: fromView)
            UIView.animateWithDuration(transitionDuration(transitionContext),
                delay: 0,
                usingSpringWithDamping: 0.7,
                initialSpringVelocity: 0.7,
                options: .BeginFromCurrentState,
                animations: { () -> Void in
                    fromView.frame = endingRect
                }, completion: { (complete) -> Void in
                    if !transitionContext.transitionWasCancelled() {
                        fromView.removeFromSuperview()
                    }
                    transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
            })
        }
    }
    

    Objective-C

    UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
        
    UIView *toView = toViewController.view;
    UIView *fromView = fromViewController.view;
    UIView *containerView = [transitionContext containerView];
    
    if(self.isPresenting) {
        //now we want to slide in from the right
        CGRect startingRect = CGRectOffset(fromView.bounds, CGRectGetWidth(fromView.bounds), 0);
        toView.frame = [containerView convertRect:startingRect fromView:fromView];
        [containerView addSubview:toView];
        [UIView animateWithDuration:[self transitionDuration:transitionContext]
                         animations:^{
                             toView.frame = [containerView convertRect:fromView.bounds
                                                              fromView:fromView];
                         }
                         completion:^(BOOL finished) {
                             [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
                         }];
    
    } else {
        //we want to slide out to the right
        [UIView animateWithDuration:[self transitionDuration:transitionContext]
                         animations:^{
                             CGRect endingRect = CGRectOffset(fromView.bounds, CGRectGetWidth(fromView.bounds), 0);
                             fromView.frame = [containerView convertRect:endingRect fromView:fromView];
                         }
                         completion:^(BOOL finished) {
                             [fromView removeFromSuperview];
                             [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
                         }];
    
    }
    

    I hope this helps someone else who came here in the same boat (if it does, an up-vote won't hurt :) )

提交回复
热议问题