如何以编程方式更改 NavigationBar 中 UIVisualEffectView 的 alpha?
Posted
技术标签:
【中文标题】如何以编程方式更改 NavigationBar 中 UIVisualEffectView 的 alpha?【英文标题】:How do you programmatically change the alpha of a UIVisualEffectView in a NavigationBar? 【发布时间】:2017-03-29 17:02:19 【问题描述】:我有一个滚动视图,我用它来控制其他元素的 alpha,具体取决于用户滚动视图的距离。
首先,我设置了模糊视图。 这里的 Alpha 似乎不需要,首先
var effect: UIBlurEffectStyle = .light
if #available(ios 10.0, *)
effect = .prominent
let blurView = UIVisualEffectView(effect: UIBlurEffect(style: effect))
blurView.alpha = 0
if let navigationBar = navigationController?.navigationBar
blurView.frame = navigationBar.bounds
self.blurView = blurView
然后在我的UIScrollViewDelegate
:
func scrollViewDidScroll(_ scrollView: UIScrollView)
var alpha = (scrollView.contentOffset.y / 200)
alpha = alpha > 1.0 ? 1.0 : alpha
blurView?.alpha = alpha
这似乎也不起作用。
关于如何实现这种效果的任何建议?谢谢!
【问题讨论】:
看起来好像您已将 blurView 添加到任何地方的视图层次结构中。 我不是,真的。但它出现了,几天来我一直觉得这很奇怪。知道为什么吗? 【参考方案1】:当您阅读Apple documentation 时,您会发现:
当使用 UIVisualEffectView 类时,避免 alpha 值 小于 1。
事实上你也应该得到一个警告:
[Warning] <UIVisualEffectView 0x7af7a3b0> is being asked to animate its opacity. This will cause the effect to appear broken until opacity returns to 1.
P.S.: 注意,我的意思是你可以改变视觉效果的 alpha,但视图可能看起来只是部分透明而不是模糊。
如果你不相信这个文档,你可以在一个空白项目中测试我下面的小例子,你可以看到,如果你改变 alpha 值,你的效果会停止正常工作:
(你可以在我的GitHUB仓库here找到下面的所有项目)
在一个空白项目中准备一个连接到 viewController 的 navigationController,如下所示:
将带有UIImageView
的通用图像放到您的viewController 的视图中,如下图:
class ViewController: UIViewController
var blurView: UIVisualEffectView!
var effect: UIBlurEffectStyle = .light
var blurEffect : UIBlurEffect!
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
// This code make more transparent our navigation
if let navigationBar = navigationController?.navigationBar
navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
navigationBar.tintColor = .white
let textAttributes = [NSForegroundColorAttributeName:UIColor.white]
navigationBar.titleTextAttributes = textAttributes
navigationBar.shadowImage = UIImage()
navigationBar.backgroundColor = UIColor(red: 0.0, green: 0.3, blue: 0.5, alpha: 0.3)
navigationBar.isTranslucent = true
override func viewDidLoad()
super.viewDidLoad()
if #available(iOS 10.0, *)
effect = .prominent
else
// Fallback on earlier versions
if let navigationBar = navigationController?.navigationBar
let noEffectView = UIVisualEffectView.init(frame: navigationBar.bounds)
self.blurEffect = UIBlurEffect(style: effect)
self.blurView = noEffectView
navigationBar.addSubview(self.blurView)
// This line below to don't blur buttons and title
navigationBar.sendSubview(toBack: self.blurView)
// Apply the effect:
Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.applyBlur), userInfo: nil, repeats: false)
func applyBlur()
print("Apply the blur effect..")
UIView.animate(withDuration: 10.2, animations:
self.blurView.effect = self.blurEffect
, completion: (finished: Bool) in
// Make test with a simple timer:
Timer.scheduledTimer(timeInterval: 0.3, target: self, selector: #selector(self.changeAlpha), userInfo: nil, repeats: true)
)
func changeAlpha()
let startNum:CGFloat = 0.0; let stopNum:CGFloat = 200.0
let randomNum = CGFloat(arc4random()) / CGFloat(UINT32_MAX) * abs(startNum - stopNum) + min(startNum, stopNum)
var alpha = (randomNum / 200)
alpha = alpha > 1.0 ? 1.0 : alpha
print("we change alpha to : \(alpha)")
self.blurView.alpha = alpha
带有模糊效果的输出:
alpha 变化期间的输出:
解决办法:
可能您不想更改 alpha 值,而是滚动期间的模糊效果量,因此解决方案可能是使用 UIViewPropertyAnimator
的新 fractionComplete
属性,仅可从iOS 10.0(如 this 其他 SO 回答中所建议)
import UIKit
@available(iOS 10.0, *)
class ViewController: UIViewController
var blurView: UIVisualEffectView!
var effect: UIBlurEffectStyle = .light
var blurEffect : UIBlurEffect!
var animator: UIViewPropertyAnimator!
override func viewWillAppear(_ animated: Bool)
super.viewWillAppear(animated)
// This code make more transparent our navigation
if let navigationBar = navigationController?.navigationBar
navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)
navigationBar.tintColor = .white
let textAttributes = [NSForegroundColorAttributeName:UIColor.white]
navigationBar.titleTextAttributes = textAttributes
navigationBar.shadowImage = UIImage()
navigationBar.backgroundColor = UIColor(red: 0.0, green: 0.3, blue: 0.5, alpha: 0.3)
navigationBar.isTranslucent = true
override func viewDidLoad()
super.viewDidLoad()
effect = .prominent
if let navigationBar = navigationController?.navigationBar
let noEffectView = UIVisualEffectView.init(frame: navigationBar.bounds)
self.blurEffect = UIBlurEffect(style: effect)
self.blurView = noEffectView
navigationBar.addSubview(self.blurView)
// This line below to don't blur buttons and title
navigationBar.sendSubview(toBack: self.blurView)
// Apply the effect:
Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.applyBlur), userInfo: nil, repeats: false)
func applyBlur()
print("Apply the blur effect..")
animator = UIViewPropertyAnimator(duration: 0.5, curve: .linear)
self.blurView.effect = self.blurEffect
animator.addAnimations
self.blurView.effect = nil
Timer.scheduledTimer(timeInterval: 0.3, target: self, selector: #selector(self.changeBlurFraction), userInfo: nil, repeats: true)
func changeBlurFraction()
let startNum:CGFloat = 0.0; let stopNum:CGFloat = 200.0
let randomNum = CGFloat(arc4random()) / CGFloat(UINT32_MAX) * abs(startNum - stopNum) + min(startNum, stopNum)
var blurFraction = (randomNum / 200)
blurFraction = blurFraction > 1.0 ? 1.0 : blurFraction
print("we change the blur fraction to : \(blurFraction)")
animator.fractionComplete = blurFraction
正如您所看到的,这改变了模糊效果而不是 alpha,每次触发计时器时,您都可以看到导航栏的模糊值不同。
诀窍是应用模糊效果并添加新动画以将效果报告为 nil,但每次都使用新的“分数”将动画更改为确切的模糊值。
输出:
【讨论】:
GitHUB 项目here 感谢亚历山德罗的详尽回答【参考方案2】:斯威夫特 5.0。只需使用以下代码:
navigationController?.navigationBar.isTranslucent = false
它用 alpha = 1 的纯色更改“0.85 alpha 效果”。
【讨论】:
【参考方案3】:由于 Apple 对实现的内部更改,UIVisualEffectView
的 Alpha 混合自 iOS 10 以及图层蒙版被破坏。
我建议使用UIViewPropertyAnimator
对象将实际效果(在您的情况下为.prominent
)转换为nil
,然后手动将fractionComplete
设置为alpha 值。它将为您提供更好的效果,并允许您以交互方式更改效果。
【讨论】:
以上是关于如何以编程方式更改 NavigationBar 中 UIVisualEffectView 的 alpha?的主要内容,如果未能解决你的问题,请参考以下文章
如何以编程方式设置 UINavigationbar 的背景颜色?
Swift - UINavigationController 栏颜色不会以编程方式更改
如何以每页为基础更改我的 NavigationBar 的背景图像?
UIScrollView.size = view.size - allAdditionalBars.size(如 TabBar 或 NavigationBar)以编程方式