如何以编程方式更改导航栏中 UIVisualEffectView 的 alpha?

2024-01-05

我有一个滚动视图,用于根据用户滚动视图的距离来控制其他元素的 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
}

这似乎也不起作用。

关于如何实现这种效果有什么建议吗?谢谢!


当你读到苹果文档 https://developer.apple.com/reference/uikit/uivisualeffectview你可以找到:

使用 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 https://github.com/aornano/UIVisualEffectView-in-a-NavigationBar-changing-alpha-)

在空白项目中准备一个连接到 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 值,而是更改滚动期间的模糊效果量所以解决方案可能是使用新的fractionComplete of UIViewPropertyAnimator财产只能从iOS 10.0(如建议的this https://stackoverflow.com/a/42608071/1894067其他答案)

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,并且每次触发计时器时,您都可以看到导航栏的不同模糊值。

诀窍是应用模糊效果并添加一个新的动画以将效果报告为零,但每次都使用新的“分数”将动画更改为模糊的确切值。

Output:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何以编程方式更改导航栏中 UIVisualEffectView 的 alpha? 的相关文章

随机推荐