UIVisualEffectView 在 iOS 14 小部件中不起作用

Posted

技术标签:

【中文标题】UIVisualEffectView 在 iOS 14 小部件中不起作用【英文标题】:UIVisualEffectView does not work in iOS 14 Widget 【发布时间】:2020-11-05 08:59:08 【问题描述】:

我放了一张图片,它会填满小部件视图。

我做了一个小视图,希望这个视图显示背后图像的模糊图像。

(图像和小视图在 ZStack 中)

我使用的代码很少(类似于Is there a method to blur a background in SwiftUI? 中的选项 2)

但结果是这样的

我认为黄色框表示“VisualEffectView 在 WidgetKit 中不起作用。”

所以我想知道是否有其他技术可以显示在图像后面显示模糊的小视图?

【问题讨论】:

【参考方案1】:

我认为黄色框表示“VisualEffectView 不起作用 WidgetKit。'

是的,特别是因为您不能在小部件中使用UIViewRepresentable。见:

Display UIViewRepresentable in WidgetKit

这意味着唯一的选择是使用 SwiftUI 代码。这里有一个可能的解决方案(选项 1):

Is there a method to blur a background in SwiftUI?
struct WidgetEntryView: View 
    var entry: Provider.Entry

    var body: some View 
        ZStack 
            Image("testImage")
                .blur(radius: 10)
        
        .edgesIgnoringSafeArea(.all)
    

【讨论】:

【参考方案2】:

我找到了一些解决方法

首先,我放原图

然后在原图上放一张应用高斯滤波的图片

并将 clipShape 添加到过滤后的图像。

clipShape 参数的对象需要像这样确认 Shape 协议

struct MyShape: Shape 
  func path(in rect: CGRect) -> Path 
    RoundedRectangle(cornerRadius: 10.0).path(...)
  

我从

中找到了高斯滤波器代码

https://gist.github.com/Zedd0202/8d3e567161d0c92e7d585bb74e926413#file-applyblur_usingclamp-swift

伪代码

ZStack 
  Image("image")
  Image("image")
    .clipShape(YourShape())
    .frame(...)
    .padding(...)

---
extension UIImage 
  func applyBlur_usingClamp(radius: CGFloat) -> UIImage 
        let context = CIContext()
        guard let ciImage = CIImage(image: self),
              let clampFilter = CIFilter(name: "CIAffineClamp"),
              let blurFilter = CIFilter(name: "CIGaussianBlur") else 
            return self
        
        
        clampFilter.setValue(ciImage, forKey: kCIInputImageKey)
        
        blurFilter.setValue(clampFilter.outputImage, forKey: kCIInputImageKey)
        blurFilter.setValue(radius, forKey: kCIInputRadiusKey)
        guard let output = blurFilter.outputImage,
              let cgimg = context.createCGImage(output, from: ciImage.extent) else 
            return self
        
        return UIImage(cgImage: cgimg)
    

---
struct YourShape: Shape 

    
    func path(in rect: CGRect) -> Path 
        RoundedRectangle(cornerRadius: 10.0)
            .path(in: CGRect(...))
    

然后你会得到这样的东西

更新

看起来小部件有某种内存限制

如果您在真实设备上运行此代码,它可能会崩溃(在我的情况下,大多数时候模拟器都可以工作)

你可以通过调整applyBlur_usingClamp方法的半径值来解决这个问题。 (250 崩溃,100 对我来说没问题)

【讨论】:

以上是关于UIVisualEffectView 在 iOS 14 小部件中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

iOS 10 上的 UIVisualEffectView 蒙版

iOS7中的UIVisualEffectView

UIVisualEffectView 在 iOS 14 小部件中不起作用

iOS 8 模糊视图(毛玻璃效果)的简单实现UIVisualEffectView

React Native:检测是不是支持 UIVisualEffectView

ios8 毛玻璃效果(UIVisualEffectView)