

下記の画像のようにNavigationBarが共用されずに、遷移する方法を知りたいので、教えていただけると嬉しく思います。

普通に画面遷移するときは、以下のようなコードを書くと思います。

[code]

    navigationController?.pushViewController(secondViewController, animated: true)
    
[/code]

しかし、これではNavigationBarが共有されてしまうと思います。

よろしくお願いします。

[![アプリ画像](https://i.stack.imgur.com/TlSwk.jpg)](https://i.stack.imgur.com/TlSwk.jpg)


CC BY-SA 3.0
2017-10-31T07:32:29.383
39177
2023-07-04T10:04:55.823
25991
question
swift ios xcode navigationbar
画面遷移前と後でNavigationBarが共有されないように遷移するには？


私の知る限り一つのNavigation Controllerでは必ずNavigation Barを共有するので、以下のように新しいNavigation
Controllerを作成して独自の遷移アニメーションでpresentして実現することになると思います。

まずUIViewControllerAnimatedTransitioningプロトコルに適合したAnimatorを実装します。このAnimatorでは遷移のアニメーションを記述します。（以下のコードではついでに遷移中に影もつけてます）

[code]

    class Animator: NSObject, UIViewControllerAnimatedTransitioning {
        var presented = false
    
        func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 1.0
        }
    
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
            let fromVC
                     = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)
            let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
    
            if presented {
                dismissTransition(transitionContext: transitionContext, toView: toVC!.view, fromView: fromVC!.view)
            } else {
                presentTransition(transitionContext: transitionContext, toView: toVC!.view, fromView: fromVC!.view)
            }
        }
    
        func presentTransition(transitionContext: UIViewControllerContextTransitioning, toView: UIView, fromView: UIView) {
            let containerView = transitionContext.containerView
            containerView.insertSubview(toView, aboveSubview: fromView)
            toView.frame = toView.frame.offsetBy(dx: containerView.frame.width, dy: 0.0)
            addShadow(to: toView)
    
            UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0.0, options: .curveEaseInOut, animations: {
                toView.frame = containerView.frame
            }) { finished in
                self.removeShadow(from: toView)
                self.presented = true
                transitionContext.completeTransition(true)
            }
        }
    
        func dismissTransition(transitionContext: UIViewControllerContextTransitioning, toView: UIView, fromView: UIView) {
            let containerView = transitionContext.containerView
            containerView.insertSubview(toView, belowSubview: fromView)
            toView.frame = containerView.bounds
            addShadow(to: fromView)
    
            UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0.0, options: .curveEaseInOut, animations: {
                fromView.frame = fromView.frame.offsetBy(dx: containerView.frame.width, dy: 0.0)
            }) { finished in
                self.removeShadow(from: fromView)
                self.presented = false
                transitionContext.completeTransition(true)
            }
        }
    
        func addShadow(to view: UIView) {
            view.layer.shadowColor = UIColor.black.cgColor
            view.layer.shadowOpacity = 0.2
            view.layer.shadowOffset = CGSize(width: -5.0, height: 0.0)
            view.layer.shadowPath = UIBezierPath(rect: view.bounds).cgPath
            view.layer.shouldRasterize = true
            view.layer.rasterizationScale = UIScreen.main.scale
        }
    
        func removeShadow(from view: UIView) {
            view.layer.shadowPath = .none
            view.layer.shadowColor = .none
            view.layer.shadowOpacity = 0.0
        }
    }
    
[/code]

次にコントローラをUIViewControllerTransitioningDelegateに適合させAnimatorを返すようにします。さらに、遷移コードを実装します。遷移は、次に表示するコントローラを新しいNavigation
Controllerに載せ、そのNavigation
Controllerをpresentしています。（このコードではボタンをタップしたら遷移するようにIBActionとして記述しています。）

[code]

    class FirstViewController: UIViewController, UIViewControllerTransitioningDelegate {
        let animator = Animator()
    
        @IBAction func buttonTapped(_ sender: Any) {
            let controller    = SecondViewController(nibName: .none, bundle: .none)
            let navController = UINavigationController(rootViewController: controller)
            navController.transitioningDelegate = self
            present(navController, animated: true)
        }
    
        func animationController(forPresented presented: UIViewController,
                                 presenting: UIViewController,
                                 source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            return animator
        }
    
        func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            return animator
        }
    }
    
[/code]

上に載せたコントローラからもとのコントローラに戻る時は、dismissメソッドを実行します。

[code]

    dismiss(animated: true)
    
[/code]


CC BY-SA 3.0
2017-11-01T02:44:13.123
39193
2017-11-01T02:44:13.123
238
39177
answer