Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UINavigationController remove drop shadow when transitioning to another VC

When using a UINavigationController and pushViewController:animated: to push another view controller onto the stack, there is always a drop shadow shown during the transition:

enter image description here

I have an app where I have a video background on the navigation controller, so I want to remove that drop shadow since it looks strange during the transition.

Is there any way to completely remove it? (I am NOT talking about UINavigationBar shadow)

like image 344
Nic Hubbard Avatar asked Jun 08 '15 22:06

Nic Hubbard


1 Answers

Solution:

// set one of viewcontrollers (usual first) as navigationController delegate

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationController?.delegate = self
    }

}

// make the view controller conform to `UINavigationControllerDelegate`

extension ViewController: UINavigationControllerDelegate {
    func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return PushPopAnimator(operation: operation)
    }
}

// The animation controller

class PushPopAnimator: NSObject, UIViewControllerAnimatedTransitioning {
    let operation: UINavigationControllerOperation

    init(operation: UINavigationControllerOperation) {
        self.operation = operation
        super.init()
    }

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.25
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        let from = transitionContext.viewController(forKey: .from)!
        let to   = transitionContext.viewController(forKey: .to)!

        let rightTransform = CGAffineTransform(translationX: transitionContext.containerView.bounds.size.width, y: 0)
        let leftTransform = CGAffineTransform(translationX: -transitionContext.containerView.bounds.size.width, y: 0)

        if operation == .push {
            to.view.transform = rightTransform
            transitionContext.containerView.addSubview(to.view)
            UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: { 
                from.view.transform = leftTransform
                to.view.transform = .identity
            }, completion: { finished in
                from.view.transform = .identity
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
            })
        } else if operation == .pop {
            to.view.transform = leftTransform
            transitionContext.containerView.insertSubview(to.view, belowSubview: from.view)
            UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
                to.view.transform = .identity
                from.view.transform = rightTransform
            }, completion: { finished in
                from.view.transform = .identity
                transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
            })
        }
    }
}
like image 68
Igor Avatar answered Sep 20 '22 08:09

Igor