-->

Custom Viewcontroller transition doesn't resiz

2019-09-19 09:04发布

问题:

I have a custom Viewcontroller Transition for the Navigation Controller in my app. When the transition is performed, it hasn't resized the content of the child viewcontroller properly. The default transition does resize it. I have added an example project on Github to demonstrate the issue.

The VC embedded in the Navigation Controller

import UIKit

class PopoverVCViewController: UIViewController, UIViewControllerTransitioningDelegate, UINavigationControllerDelegate {

    let animator = Animator()

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationController?.delegate = self
        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            animator.reverse = operation == .Pop
            return animator
    }

}

The animator

class Animator: NSObject, UIViewControllerAnimatedTransitioning {

    var reverse: Bool = false

    func animateTransition(transitionContext: UIViewControllerContextTransitioning) {

        // get reference to our fromView, toView and the container view that we should perform the transition in
        let container = transitionContext.containerView()!
        let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)!
        let toView = transitionContext.viewForKey(UITransitionContextToViewKey)!

        // set up from 2D transforms that we'll use in the animation
        let offScreenRight = CGAffineTransformMakeTranslation(container.frame.width, 0)
        let offScreenLeft = CGAffineTransformMakeTranslation(-container.frame.width, 0)

        // start the toView to the right of the screen
        if (self.reverse == false) {
            toView.transform = offScreenRight
        }
        else {
            toView.transform = offScreenLeft
        }

        // add the both views to our view controller
        container.addSubview(toView)
        container.addSubview(fromView)

        // get the duration of the animation
        // DON'T just type '0.5s' -- the reason why won't make sense until the next post
        // but for now it's important to just follow this approach
        let duration = self.transitionDuration(transitionContext)

        // perform the animation!
        // for this example, just slid both fromView and toView to the left at the same time
        // meaning fromView is pushed off the screen and toView slides into view
        // we also use the block animation usingSpringWithDamping for a little bounce
        UIView.animateWithDuration(duration, delay: 0.0, usingSpringWithDamping: 1.0, initialSpringVelocity: 0.0, options: UIViewAnimationOptions.CurveEaseInOut, animations: {

            if (self.reverse == false) {
                fromView.transform = offScreenLeft
            }
            else {
                fromView.transform = offScreenRight
            }

            toView.transform = CGAffineTransformIdentity

            }, completion: { finished in

                // tell our transitionContext object that we've finished animating
                transitionContext.completeTransition(true)

        })

    }

    // return how many seconds the transiton animation will take
    func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
        return 0.3
    }

    // MARK: UIViewControllerTransitioningDelegate protocol methods

    // return the animataor when presenting a viewcontroller
    // remmeber that an animator (or animation controller) is any object that aheres to the UIViewControllerAnimatedTransitioning protocol
    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return self
    }

    // return the animator used when dismissing from a viewcontroller
    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return self
    }

}

回答1:

You can set the frame of toView to match the height and width of fromView :

let container = transitionContext.containerView()!
let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)!
let toView = transitionContext.viewForKey(UITransitionContextToViewKey)!

toView.frame = CGRectMake(toView.frame.origin.x, toView.frame.origin.y, fromView.frame.width, fromView.frame.height)


回答2:

or like this:

UIViewController* toController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController* fromController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];

and then setup this near the end of your animation routine:

toController.view.frame=fromController.view.frame;