【问题标题】:Short UINavigationBar with curved edges and transparent status bar带有弯曲边缘和透明状态栏的短 UINavigationBar
【发布时间】:2017-12-14 00:05:08
【问题描述】:

如何使用导航控制器实现此效果。

我在UINavigationController 中仅嵌入了一个 VC,它是否以模态方式呈现在另一个 VC 之上。到目前为止一切都很好,但我想实现如下所示的效果,其中导航栏较短,边缘弯曲,状态栏部分透明,露出底部视图控制器的状态栏。

这是迄今为止我在故事板中的内容。

到目前为止,我已经能够通过子类化UINavigationController 为导航栏实现圆角边缘。但是我不知道如何使导航栏从顶部变短:

class ComposeNavigController: UINavigationController {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        self.definesPresentationContext = true
        self.providesPresentationContextTransitionStyle = true
        self.modalPresentationCapturesStatusBarAppearance = false
        self.modalPresentationStyle = .overFullScreen


    }

    override func viewDidLoad() {
        super.viewDidLoad()
            view.clipsToBounds = true
            view.layer.cornerRadius = 16.0
            view.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
            view.layer.shadowOffset = .zero
            view.layer.shadowColor = UIColor.black.cgColor
            view.layer.shadowRadius = 16.0
            view.layer.shadowOpacity = 0.5
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        view.layer.shadowPath = UIBezierPath(rect: view.bounds).cgPath
    }

}

效果很好并且可以弯曲边缘。

【问题讨论】:

    标签: ios swift uinavigationcontroller uinavigationbar uistatusbar


    【解决方案1】:

    好的,除了我的问题中的 UINavigationController 子类之外,这是我必须做的。我必须使用UIViewControllerAnimatedTransitioning delegate 来实现我想要的。

    我创建了两个子类NSObject 并符合上述协议。

    第一个是 present 转换-

    import UIKit
    
    class ComposePresentTransitionController: NSObject, UIViewControllerAnimatedTransitioning {
    
        func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 0.6
        }
    
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    
            let fromViewController = transitionContext.viewController(forKey: .from)!
            let toViewController = transitionContext.viewController(forKey: .to)!
            let containerView = transitionContext.containerView
    
            let screenBounds = UIScreen.main.bounds
            let topOffset: CGFloat = UIApplication.shared.statusBarFrame.height
    
            var finalFrame = transitionContext.finalFrame(for: toViewController)
            finalFrame.origin.y += topOffset
            finalFrame.size.height -= topOffset
    
            toViewController.view.frame = CGRect(x: 0.0, y: screenBounds.size.height,
                                                 width: finalFrame.size.width,
                                                 height: finalFrame.size.height)
            containerView.addSubview(toViewController.view)
    
            UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0.0, usingSpringWithDamping: 0.8, initialSpringVelocity: 1.0, options: .curveEaseOut, animations: {
                toViewController.view.frame = finalFrame
                fromViewController.view.alpha = 0.3
            }) { (finished) in
                transitionContext.completeTransition(finished)
            }
    
            UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0.0, options: .curveEaseOut,
                           animations: {
    
            }) { (finished) in
    
            }
        }
    }
    

    dismiss 转换第二-

    import UIKit
    
    class ComposeDismissTransitionController: NSObject, UIViewControllerAnimatedTransitioning {
    
        func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return 0.3
        }
    
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    
            let fromViewController = transitionContext.viewController(forKey: .from)!
            let toViewController = transitionContext.viewController(forKey: .to)!
    
            let screenBounds = UIScreen.main.bounds
            var finalFrame = fromViewController.view.frame
            finalFrame.origin.y = screenBounds.size.height
    
            UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0.0, options: .curveEaseIn,
                           animations: {
                            fromViewController.view.frame = finalFrame
                            toViewController.view.alpha = 1.0
            }) { (finished) in
                fromViewController.view.removeFromSuperview()
                transitionContext.completeTransition(finished)
            }
        }
    }
    

    然后,从将要呈现此视图控制器的视图控制器中,该视图控制器需要符合UIViewControllerTransitioningDelegate 协议并实现animationController:forPresentedanimationController:forDismissed 这样的方法-

    extension PresentingVC: UIViewControllerTransitioningDelegate {
    
        func animationController(forPresented presented: UIViewController,
                                 presenting: UIViewController,
                                 source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            return ComposePresentTransitionController()
        }
    
        func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            return ComposeDismissTransitionController()
        }
    }
    

    完成后,PresentingVC 需要将UIViewControllerTransitioningDelegate 设置为self,这在prepareForSegue 中完成-

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            super.prepare(for: segue, sender: sender)
            segue.destination.transitioningDelegate = self
        }
    

    如果您像我一样讨厌 segue,那么您也可以通过代码中的按钮的 IBAction 执行此操作。

    @IBAction func composeTap(_ sender: Any) {
            let composeVC = self.storyboard?.instantiateViewController(withIdentifier: "compose") as! ComposeNavigController //this should be the navigation controller itself not the embedded viewcontroller
            composeVC.transitioningDelegate = self
            self.present(composeVC, animated: true, completion: nil)
        }
    

    就是这样...现在,只要点击按钮以模态显示撰写屏幕,它就会以我想要的效果模态动画。我添加了一点弹跳效果只是为了好玩:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多