如何以编程方式更改 NavigationBar 中 UIVisualEffectView 的 alpha? [英] How do you programmatically change the alpha of a UIVisualEffectView in a NavigationBar?

查看:46
本文介绍了如何以编程方式更改 NavigationBar 中 UIVisualEffectView 的 alpha?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个滚动视图,我用它来控制其他元素的 alpha,具体取决于用户向下滚动视图的深度.

首先,我设置了模糊视图.这里的 Alpha 好像不带,首先

var 效果:UIBlurEffectStyle = .light如果#available(iOS 10.0, *) {效果 = .prominent}让 blurView = UIVisualEffectView(effect: UIBlurEffect(style: effect))模糊视图.alpha = 0if let navigationBar = navigationController?.navigationBar {blurView.frame = navigationBar.bounds}self.blurView = 模糊视图

然后在我的 UIScrollViewDelegate 中:

func scrollViewDidScroll(_ scrollView: UIScrollView) {var alpha = (scrollView.contentOffset.y/200)阿尔法=阿尔法>1.0 ?1.0:阿尔法模糊视图?.alpha = alpha}

这似乎也不起作用.

关于如何实现这种效果的任何建议?谢谢!

解决方案

当你阅读

事实上你也应该得到一个警告:

[警告] 被要求为其不透明度设置动画.这将导致效果出现损坏,直到不透明度恢复为 1.

PS: 请注意,我的意思是您可以更改视觉效果的 Alpha,但视图可能仅显示为部分透明而不是模糊.

如果你不相信这个文档,你可以在下面的一个空白项目中测试我的小例子,你可以看到,如果你改变 alpha 值,你的效果就会停止正常工作:

(您可以在我的 GitHUB 存储库中找到以下所有项目

将带有 UIImageView 的通用图像放到 viewController 的视图中,如下图所示:

class ViewController: UIViewController {var blurView:UIVisualEffectView!var 效果:UIBlurEffectStyle = .lightvar blurEffect : UIBlurEffect!覆盖 func viewWillAppear(_ 动画:布尔){super.viewWillAppear(动画)//此代码使我们的导航更加透明if let navigationBar = navigationController?.navigationBar {navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default)navigationBar.tintColor = .white让 textAttributes = [NSForegroundColorAttributeName:UIColor.white]navigationBar.titleTextAttributes = textAttributesnavigationBar.shadowImage = UIImage()navigationBar.backgroundColor = UIColor(红色:0.0,绿色:0.3,蓝色:0.5,alpha:0.3)navigationBar.isTranslucent = true}}覆盖 func viewDidLoad() {super.viewDidLoad()如果#available(iOS 10.0, *) {效果 = .prominent} 别的 {//回退到早期版本}if let navigationBar = navigationController?.navigationBar {让 noEffectView = UIVisualEffectView.init(frame: navigationBar.bounds)self.blurEffect = UIBlurEffect(style: effect)self.blurView = noEffectViewnavigationBar.addSubview(self.blurView)//下面这行不要模糊按钮和标题navigationBar.sendSubview(toBack: self.blurView)//应用效果:Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self.applyBlur), userInfo: nil, repeats: false)}}功能应用模糊(){print("应用模糊效果..")UIView.animate(withDuration: 10.2, 动画: {self.blurView.effect = self.blurEffect},完成:{(完成:Bool)在//用一个简单的计时器进行测试:Timer.scheduledTimer(timeInterval: 0.3, target: self, selector: #selector(self.changeAlpha), userInfo: nil, repeats: true)})}func changeAlpha() {让 startNum:CGFloat = 0.0;让 stopNum:CGFloat = 200.0让 randomNum = CGFloat(arc4random())/CGFloat(UINT32_MAX) * abs(startNum - stopNum) + min(startNum, stopNum)var alpha = (randomNum/200)阿尔法=阿尔法>1.0 ?1.0:阿尔法print("我们将 alpha 更改为:\(alpha)")self.blurView.alpha = alpha}}

带有模糊效果的输出:

Alpha 更改期间的输出:

解决方案:

可能您不想更改 alpha 值,而是在滚动期间更改模糊效果的量,因此解决方案可能是使用 fractionComplete 的新 fractionComplete>UIViewPropertyAnimator 属性仅从 iOS 10.0 可用(如

I have a scroll view that I'm using to control the alpha of other elements depending on how far down the view the user scrolls.

First, I set up the blur view. Alpha here doesn't seem to take, firstly

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

Then in my UIScrollViewDelegate:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
        var alpha = (scrollView.contentOffset.y / 200)
        alpha = alpha > 1.0 ? 1.0 : alpha

        blurView?.alpha = alpha
}

This doesn't seem to be working either.

Any advice on how to achieve this effect? Thanks!

解决方案

When you read the Apple documentation you can find:

When using the UIVisualEffectView class, avoid alpha values that are less than 1.

In fact you should obtain also a warning:

[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.: Pay attention, what I mean is that you can change the alpha of the visual effects but the view could appear as simply partially transparent rather than blurred.

If you don't believe in this documentation, you can test my little example below to a blank project and you can see that, if you change alpha value, your effect stop to work correctly:

(You can find all the project below to my GitHUB repository here)

Prepare in a blank project a navigationController connected to a viewController like this:

Put a generic image with an UIImageView to the view of your viewController, like this image:

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
    }
}

Output with the blur effect:

Output during alpha changes:

A solution:

Probably you don't want to change the alpha value but the amount of blur effect during the scrolling so the solution could be to use the new fractionComplete of UIViewPropertyAnimator property available only from iOS 10.0 (as suggested in this other SO answer)

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
    }
}

As you can see this change the blur effect not the alpha and every time the timer is fired you can see a different value of blur to your navigationBar.

The trick is to apply the blur effect and add a new animation to report the effect to nil but everytime with a new "fraction" to change the animation to that exact value of blur.

Output:

这篇关于如何以编程方式更改 NavigationBar 中 UIVisualEffectView 的 alpha?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆