【问题标题】:Is there a method to blur a background in SwiftUI?SwiftUI 中有没有一种模糊背景的方法?
【发布时间】:2019-10-29 20:18:09
【问题描述】:

我希望模糊视图的背景,但不想闯入 UIKit 来完成它(例如 UIVisualEffectView)我正在挖掘文档但一无所获,似乎没有办法实时剪辑背景并对其应用效果。是我错了还是调查方式不对?

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    1。 Native SwiftUI 方式:

    只需在需要模糊的任何内容上添加.blur() 修饰符:

    Image("BG")
       .blur(radius: 20)
    

    注意视图的顶部和底部

    请注意您可以Group多个视图并将它们模糊在一起。


    2。视觉效果视图:

    您可以从 UIKit 中带上级长UIVisualEffectView

    VisualEffectView(effect: UIBlurEffect(style: .dark))
    

    有了这个小结构:

    struct VisualEffectView: UIViewRepresentable {
        var effect: UIVisualEffect?
        func makeUIView(context: UIViewRepresentableContext<Self>) -> UIVisualEffectView { UIVisualEffectView() }
        func updateUIView(_ uiView: UIVisualEffectView, context: UIViewRepresentableContext<Self>) { uiView.effect = effect }
    }
    


    3。 iOS 15:材料

    一行代码即可使用iOS预定义素材:

    .background(.ultraThinMaterial)
    

    【讨论】:

    • 我喜欢你可以对任何东西进行 .blur 处理!
    • 这是我见过的最简洁的 Representable 用法。很有帮助。
    【解决方案2】:

    我还没有找到在 SwiftUI 中实现这一点的方法,但是您可以通过 UIViewRepresentable 协议使用 UIKit 的东西。

    struct BlurView: UIViewRepresentable {
    
        let style: UIBlurEffect.Style
    
        func makeUIView(context: UIViewRepresentableContext<BlurView>) -> UIView {
            let view = UIView(frame: .zero)
            view.backgroundColor = .clear
            let blurEffect = UIBlurEffect(style: style)
            let blurView = UIVisualEffectView(effect: blurEffect)
            blurView.translatesAutoresizingMaskIntoConstraints = false
            view.insertSubview(blurView, at: 0)
            NSLayoutConstraint.activate([
                blurView.heightAnchor.constraint(equalTo: view.heightAnchor),
                blurView.widthAnchor.constraint(equalTo: view.widthAnchor),
            ])
            return view
        }
    
        func updateUIView(_ uiView: UIView,
                          context: UIViewRepresentableContext<BlurView>) {
    
        }
    
    }
    

    演示

    struct ContentView: View {
    
        var body: some View {
            NavigationView {
                ZStack {
                    List(1...100) { item in
                        Rectangle().foregroundColor(Color.pink)
                    }
                    .navigationBarTitle(Text("A List"))
                    ZStack {
                        BlurView(style: .light)
                            .frame(width: 300, height: 300)
                        Text("Hey there, I'm on top of the blur")
    
                    }
                }
            }
        }
    
    }
    

    我使用ZStack 将视图放在上面。

    ZStack {
     // List
     ZStack {
        // Blurred View
        // Text
     }
    }
    

    最终看起来像这样:

    【讨论】:

    • 这会模糊视图中的内容,但我正在寻找允许模糊底层内容的东西,就像 UI VisualEffectView 或 navigationController 的工作方式一样,而您可以拥有一个模糊它覆盖的内容的项目并且仅在 BlurringView 的框架内,而不是 BlurringView 的子内容。我想更像是 BlendMode 的工作原理。
    • 这不是在做什么吗?
    • 如何减少模糊量?
    • 当我第二次浏览页面时,没有出现模糊视图。是不是因为updateUIView函数是空的?
    • 这真是天才!它有效 - 如果您使用样式“systemChromeMaterial”,它会模仿菜单栏的模糊/透明度。干得好。
    【解决方案3】:

    最简单的方法是 Richard Mullinix 的here

    struct Blur: UIViewRepresentable {
        var style: UIBlurEffect.Style = .systemMaterial
    
        func makeUIView(context: Context) -> UIVisualEffectView {
            return UIVisualEffectView(effect: UIBlurEffect(style: style))
        }
    
        func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
            uiView.effect = UIBlurEffect(style: style)
        }
    }
    

    然后只需在代码中的某处使用它,例如背景:

        //...
        MyView()
            .background(Blur(style: .systemUltraThinMaterial))
    

    【讨论】:

      【解决方案4】:

      正如@mojtaba 所提到的,当您将resizable() 与blur() 一起设置时,在图像顶部看到白色阴影是非常奇怪的。

      简单的技巧是将图像填充提高到-ve。

       var body: some View {
      
              return
                  ZStack {
      
                      Image("background_2").resizable()
                          .edgesIgnoringSafeArea(.all)
                          .blur(radius: 5)
                          .scaledToFill()
                          .padding(-20) //Trick: To escape from white patch @top & @bottom
      
      
              }
        }
      

      结果:

      【讨论】:

      • 您可以向.blur 修饰符添加另一个参数。如果你使用.blur(radius: 5, opaque: true),它应该去掉那个白色阴影。
      【解决方案5】:
      @State private var amount: CGFLOAT = 0.0
      
      var body: some View {
          VStack{
             Image("Car").resizable().blur(radius: amount, opaque: true)
          }
      }
      

      使用带有模糊功能的“Opaque: true”将消除白噪声

      【讨论】:

        【解决方案6】:

        iOS 15 中的新功能,SwiftUIUIVisualEffectView 非常简单等效,它结合了 ZStackbackground() 修饰符和一系列内置材料。

        ZStack {
            Image("niceLook")
        
            Text("Click me")
                .padding()
                .background(.thinMaterial)
        }
        

        您可以使用多种材质类型中的一种来调整材质的“厚度”——背景内容的透光程度。从最薄到最厚,分别是:

        .ultraThinMaterial
        .thinMaterial
        .regularMaterial
        .thickMaterial
        .ultraThickMaterial
        

        【讨论】:

        • 这正是我当时所寻找的。​​span>
        【解决方案7】:

        有一个非常有用但不幸的是私人(感谢Apple)课程CABackdropLayer

        它绘制了下面图层的副本,我发现它在使用blend mode或滤镜时很有用,它也可以用于模糊效果

        代码

        open class UIBackdropView: UIView {
        
          open override class var layerClass: AnyClass {
            NSClassFromString("CABackdropLayer") ?? CALayer.self
          }
        }
        
        public struct Backdrop: UIViewRepresentable {
        
          public init() {}
        
          public func makeUIView(context: Context) -> UIBackdropView {
            UIBackdropView()
          }
        
          public func updateUIView(_ uiView: UIBackdropView, context: Context) {}
        }
        
        public struct Blur: View {
        
          public var radius: CGFloat
          public var opaque: Bool
        
          public init(radius: CGFloat = 3.0, opaque: Bool = false) {
            self.radius = radius
            self.opaque = opaque
          }
        
          public var body: some View {
            Backdrop()
              .blur(radius: radius, opaque: opaque)
          }
        }
        

        用法

        struct Example: View {
        
          var body: some View {
            ZStack {
              YourBelowView()
              YourTopView()
                .background(Blur())
                .background(Color.someColor.opacity(0.4))
            }
          }
        }
        

        Source

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-04-12
          • 1970-01-01
          • 2022-09-26
          • 1970-01-01
          • 2021-12-22
          • 1970-01-01
          • 2020-12-13
          • 1970-01-01
          相关资源
          最近更新 更多