通常,半透明UINavigationBar
在白色背景上方呈浅灰色。
但是,iOS 11中的许多导航栏都有白色。
例如,“文件”应用中的导航栏为白色且半透明,与将barTintColor
设置为白色明显不同。
如何在UINavigationBar
?
答案 0 :(得分:1)
答案 1 :(得分:0)
我试图构建与Files应用程序样式相同的应用程序,但最终遇到了相同的问题。
当barTintColor
为非零时,UINavigationBar
会禁用半透明效果,并且似乎没有公开的方式强制将其重新启用。
不过,我认为有一种实现此效果的合理方法:您可以用自己的UIVisualEffectView
替换导航栏的背景视图。
可以通过向其提供虚拟UIImage
对象来同时抑制导航栏的背景视图和分隔符视图。
navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationBar.shadowImage = UIImage()
您将需要创建自己的UINavigationBar
子类,隐藏这两个视图,然后添加自己的UIVisualEffectView
子视图并将其放置在始终位于视图堆栈底部的位置。
这不是一个了不起的解决方案,但希望它可以在导航栏类的内部黑客最少的情况下产生所需的效果。
答案 2 :(得分:0)
因此,我花了大量时间对此进行了研究,并且找到了答案,但是请注意:这非常,非常棘手。
因此,负责在导航栏上创建此灰色发光的视图称为_UIVisualEffectBackdropView
。更具体地说,此视图的图层上附加了四个过滤器(所有过滤器都是专用的CAFilter
),第一个过滤器名为luminanceCurveMap
,为导航栏创建此灰色。所以我的解决办法是
_UIVisualEffectBackdropView
的视图层次结构中找到UINavigationBar
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
(例如,仅viewDidAppear
,viewWillAppear
无效)
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)
}
}
}
我知道很多,但这就是我想到的。它保留了所有本机的半透明行为,同时为我提供了所需的外观。