简体   繁体   English

修复 UIVisualEffectView 额外的光线模糊在白色背景上呈灰色

[英]Fix UIVisualEffectView extra light blur being gray on white background

Apple provides this live blurring view class UIVisualEffectView and you use it with a UIBlurEffect which takes one of three available UIBlurEffectStyle s : Apple 提供了这个实时模糊视图 class UIVisualEffectView ,你可以将它与UIBlurEffect一起使用,它采用三个可用UIBlurEffectStyle之一:

enum UIBlurEffectStyle : Int {
    case ExtraLight
    case Light
    case Dark
}

Now for demo purposes I set up two effect views with the styles Light and ExtraLight :现在出于演示目的,我使用 styles LightExtraLight设置了两个效果视图:

let lightBlur = UIBlurEffect(style: UIBlurEffectStyle.Light)
let extraLightBlur = UIBlurEffect(style: UIBlurEffectStyle.ExtraLight)

let lightView = UIVisualEffectView(effect: lightBlur)
lightView.frame = CGRectMake(10, 30, 150, 150)
self.view.addSubview(lightView)

let extraLightView = UIVisualEffectView(effect: extraLightBlur)
extraLightView.frame = CGRectMake(160, 30, 150, 150)
self.view.addSubview(extraLightView)

So far so good, everything works as expected, they blur images:到目前为止一切顺利,一切都按预期进行,它们模糊了图像:

图片

and kind of work on colors, too:以及在 colors 上的工作:

黑色的 红色的

but when it comes to a white background this happens:但是当涉及到白色背景时,会发生这种情况:

白色的

The Light effect on the left works as expected, but the ExtraLight effect on the right leaves some kind of gray square behind.左侧的Light效果按预期工作,但右侧的ExtraLight效果留下某种灰色方块。

Now the question: Is there any kind of trick or method that would enable me to use an extra light blur effect on white background (with live blurring support) AND remove that ugly gray shadow?现在的问题是:是否有任何技巧或方法可以让我在白色背景上使用额外的光模糊效果(支持实时模糊)并移除那个丑陋的灰色阴影?

As far as I know the additional tint is a built-in feature of the UIVisualEffectView class.据我所知,额外的色调是UIVisualEffectView类的内置功能。 If you examine the view hierarchy with Xcode, you can see that there are two default subviews in the visual effect view instance: UIVisualEffectBackdropView and UIVisualEffectSubview .如果您使用 Xcode 检查视图层次结构,您可以看到视觉效果视图实例中有两个默认子视图: UIVisualEffectBackdropViewUIVisualEffectSubview (I assume that these are private classes.) If you inspect UIVisualEffectSubview you can see that it has a background color which causes the unwanted tint that you've noticed. (我假设这些是私有类。)如果您检查UIVisualEffectSubview您可以看到它具有导致您注意到的不需要的色调的背景颜色。

I am not sure if there's an officially supported way to remove it, but you can modify this background color by filtering to the name of the private subview:我不确定是否有官方支持的删除它的方法,但是您可以通过过滤到私有子视图的名称来修改此背景颜色:

if let vfxSubView = visualEffectView.subviews.first(where: {
    String(describing: type(of: $0)) == "_UIVisualEffectSubview"
}) {
    vfxSubView.backgroundColor = UIColor.white.withAlphaComponent(0.7)
}

(Swift 5 compatible) (兼容 Swift 5)

The default tint is around 70% opacity, so the easiest is to use the target background color with 0.7 alpha component.默认色调约为 70% 不透明度,因此最简单的方法是使用具有 0.7 alpha 分量的目标背景颜色。

I've also noticed that this might reset to the default value if the visual effect contains a custom subview.我还注意到,如果视觉效果包含自定义子视图,这可能会重置为默认值。 If I add this same snippet to the viewDidLayoutSubviews function of the view's controller, then it will keep the custom background color even after the built-in subview is updated.如果我将这个相同的片段添加到视图控制器的viewDidLayoutSubviews函数中,那么即使在内置子视图更新后,它也会保持自定义背景颜色。

Here's an example with a dark blur effect style.这是一个带有深色模糊效果样式的示例。 The top part shows the default tint and the bottom version has a custom black background color with 70% opacity.顶部显示默认色调,底部版本具有自定义黑色背景色,不透明度为 70%。

在此处输入图片说明

If you just want the blur and your blurred view is gonna be stationary, you could use the UIImageEffects class and change the tintColor to a "full" white:如果您只想要模糊并且您的模糊视图将是静止的,您可以使用UIImageEffects类并将tintColor更改为“全”白色:

- (UIImage *)applyExtraLightEffect
{
    UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82];
    return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
}

As far as I know you can't change it in the UIVisualEffectView .据我所知,您无法在UIVisualEffectView更改它。

You can try :你可以试试:

var visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .Light))    
visualEffectView.frame = imageView.bounds
imageView.addSubview(visualEffectView)

Simple Solution简单的解决方案

I could find a simple solution inspired by Shannon Hughes' Blog Post .我可以找到一个受香农休斯博客文章启发的简单解决方案。 Just add a white background color with transparency to the effect view.只需在效果视图中添加具有透明度的白色背景色即可。 I don't know if it is exactly like extraLight but for me it is close enough.我不知道它是否与extraLight完全一样,但对我来说它已经足够接近了。

let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
visualEffectView.frame = sectionHeaderView.bounds
visualEffectView.backgroundColor = UIColor(white: 1.0, alpha: 0.9)
sectionHeaderView.addSubview(visualEffectView)

The following code should do the trick to give it a the desired tint:以下代码应该可以为它提供所需的色调:

let visualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .regular))
visualEffectView.subviews.forEach { subview in
    subview.backgroundColor = UIColor.blue.withAlphaComponent(0.2)
}

Important Note:重要的提示:

I wouldn't recommend adding a check for "_UIVisualEffectSubview" since this class can change on subsequent iOS updates.我不建议添加对“_UIVisualEffectSubview”的检查,因为此 class 可以在后续的 iOS 更新中更改。 Also, there is a possibility of app getting rejected because of this.此外,应用程序可能因此而被拒绝。

iOS 15 has the nice iOS 15有nice

.background(.ultraThinMaterial)

but it still suffers from the nasty grey tint.但它仍然受到令人讨厌的灰色调的影响。 Wish there was an option to blur background views without any tint.希望有一个选项可以在没有任何色调的情况下模糊背景视图。

I tried a simple color-correct hack which worked for my background color but only in light mode!我尝试了一个简单的颜色校正技巧,它适用于我的背景颜色,但仅适用于灯光模式! For dark mode I just made the background solid black (no translucent blur)对于暗模式,我只是将背景设为纯黑色(没有半透明模糊)

.background(
    // negate the slight grey tint of ultrathinmaterial
    Color("materialTintColorCorrect")
        .background(.ultraThinMaterial)
)

My "materialTintColorCorrect" color asset was #F0F8FF 27% opacity for light mode and #000000 100% opacity for dark.我的“materialTintColorCorrect”颜色资产是#F0F8FF 27% 的不透明度用于亮模式和#000000 100% 的不透明度用于暗模式。

let vc = UIViewController()
vc.view.frame = self.view!.frame
let efv = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.light))
efv.frame = vc.view.frame
vc.view.addSubview(efv)
self.addChildViewController(vc)
self.view.addSubview(vc.view)
// below method has a bug
// self.present(vc, animated: true, completion:nil)

I would recommend adding your extraLightView to a view of UIColor(white: 1.0, alpha: 0.x) , where x can be modified based on the scroll view's contentOffset .我建议将您的extraLightView添加到UIColor(white: 1.0, alpha: 0.x)的视图中,其中x可以根据滚动视图的contentOffset进行修改。 When there's nothing behind the view, your extraLightView will be white when x is 1. When you scroll and modify x , you won't be modifying the UIVisualEffectView (which is highly discouraged), but rather its parent view, which is perfectly safe.当视图后面没有任何东西时,当x为 1 时,您的extraLightView将是白色的。当您滚动和修改x ,您将不会修改UIVisualEffectView (这是非常不鼓励的),而是修改它的父视图,这是完全安全的。

Works with Swift 5适用于 Swift 5

My way of making the visual effect view completely white when the background view is white.当背景视图为白色时,我使视觉效果视图完全白色的方法。

let blurView = UIVisualEffectView(effect: UIBlurEffect(style: .light))
blurView.backgroundColor = UIColor.white.withAlphaComponent(0.7)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM