创建白色半透明的UINavigationBar

时间:2018-01-09 13:44:11

标签: ios swift

通常,半透明UINavigationBar在白色背景上方呈浅灰色。

Image 1

但是,iOS 11中的许​​多导航栏都有白色。 例如,“文件”应用中的导航栏为白色且半透明,与将barTintColor设置为白色明显不同。

Image 2 Image 3

如何在UINavigationBar

上实现此类效果

3 个答案:

答案 0 :(得分:1)

  1. 将导航栏的barTintColor设置为白色。
  2. 之后,子类UINavigationBar并将阴影图像设置为空UIImage

    class CustomNavBar: UINavigationBar {
       override func awakeFromNib() {
          super.awakeFromNib()
          shadowImage = UIImage()
       }
    }
    
  3. 最后,将导航栏的类设置为刚刚创建的自定义导航栏类​​。

  4. <强>结果

    translucent navigation bar, white background

    translucent navigation bar, partially black background

答案 1 :(得分:0)

我试图构建与Files应用程序样式相同的应用程序,但最终遇到了相同的问题。

barTintColor为非零时,UINavigationBar会禁用半透明效果,并且似乎没有公开的方式强制将其重新启用。

不过,我认为有一种实现此效果的合理方法:您可以用自己的UIVisualEffectView替换导航栏的背景视图。

可以通过向其提供虚拟UIImage对象来同时抑制导航栏的背景视图和分隔符视图。

navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationBar.shadowImage = UIImage()

您将需要创建自己的UINavigationBar子类,隐藏这两个视图,然后添加自己的UIVisualEffectView子视图并将其放置在始终位于视图堆栈底部的位置。

这不是一个了不起的解决方案,但希望它可以在导航栏类的内部黑客最少的情况下产生所需的效果。

答案 2 :(得分:0)

因此,我花了大量时间对此进行了研究,并且找到了答案,但是请注意:这非常,非常棘手。

因此,负责在导航栏上创建此灰色发光的视图称为_UIVisualEffectBackdropView。更具体地说,此视图的图层上附加了四个过滤器(所有过滤器都是专用的CAFilter),第一个过滤器名为luminanceCurveMap,为导航栏创建此灰色。所以我的解决办法是

  1. _UIVisualEffectBackdropView的视图层次结构中找到UINavigationBar
  2. 删除其图层的luminanceCurveMap过滤器。

这是我创建的用于在层次结构中找到_UIVisualEffectBackdropView的函数:

extension UIView {
    fileprivate static func findRecursively(typeName: String, in view: UIView) -> UIView? {
        let typeOf = type(of: view)
        if String(describing: typeOf) == typeName {
            return view
        } else {
            for subview in view.subviews {
                if let found = UIView.findRecursively(typeName: typeName, in: subview) {
                    return found
                }
            }
            return nil
        }
    }
}

然后在您的自定义viewDidAppear子类中覆盖UINavigationController(例如,仅viewDidAppearviewWillAppear无效)

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    if let backdrop = UIView.findRecursively(typeName: "_UIVisualEffectBackdropView", in: navigationBar) {
        let luminanceCurveMapIndex = backdrop.layer.filters?.firstIndex { filter in
            if let caFilter = filter as? NSObject, let name = caFilter.value(forKey: "name") as? String {
                return name == "luminanceCurveMap"
            } else {
                return false
            }
        }
        if let index = luminanceCurveMapIndex {
            backdrop.layer.filters?.remove(at: index)
        }
    }
}

我知道很多,但这就是我想到的。它保留了所有本机的半透明行为,同时为我提供了所需的外观。