如何在 SwiftUI 中使用 .Blur 作为 ViewModifier 在所有视图之上添加模糊叠加

问题描述 投票:0回答:1

我创建了一个

viewModifier
,添加后会模糊视图。

问题是当我将其添加到所有内容的父视图上时,所有视图都会以不同的方式模糊。

我认为这是因为它会转到所有内容并单独模糊每个内容,而不是向父视图添加叠加模糊。

我使用了 Swift UI 的原生模糊,因为

UIBlurEffect
的配置非常有限,即我无法将模糊强度调整为特定值。

这是在父ZStack中添加修改器时的情况:

当我仅将其添加到背景图像时:

将其添加到背景图像看起来不错,但我需要它位于所有视图之上。这是我的代码:

主视图

import SwiftUI

struct BlurViewDemo: View {
    @State private var isPressed = true
    @State private var blurColor: BlurColor = .none
    var body: some View {
        ZStack {
            GeometryReader { proxy in
                let frame = proxy.frame(in: .global)
                Image("blur-view-demo-image")
                    .resizable()
                    .frame(width: frame.size.width, height: frame.size.height)
                    // When added here only the background image is blurred.
                    .modifier(
                        BlurModifier(
                            showBlur: $isPressed, blurColor: $blurColor
                        )
                    )
                
            }
            
            VStack(spacing: 30) {
                // TITLE STYLE
                Text(getSelectedBlurTitle())
                    .font(.system(size: 60))
                    .offset(y: -40)
                    .foregroundColor(
                        blurColor == .dark  && isPressed ? .white : .black
                    )
                
                // TOGGLE BLUR BUTTON
                Button(action: {
                    isPressed.toggle()
                }, label: {
                    Text(isPressed ? "Blur: On" : "Blur: Off")
                        .foregroundColor(.white)
                })
                .frame(width: 80, height: 40)
                .background(Color(#colorLiteral(red: 0.2, green: 0.4, blue: 0.4, alpha: 1)))
                
                // DEFAULT BUTTON
                Button(action: {
                    isPressed = true
                    blurColor = .none
                }, label: {
                    Text("Default")
                        .foregroundColor(.white)
                })
                .frame(width: 80, height: 40)
                .background(Color.gray)
                
                // LIGHT BUTTON
                Button(action: {
                    isPressed = true
                    blurColor = .light
                }, label: {
                    Text("Light")
                        .foregroundColor(.black)
                })
                .frame(width: 80, height: 40)
                .background(Color.white)
                
                // DARK BUTTON
                Button(action: {
                    isPressed = true
                    blurColor = .dark
                }, label: {
                    Text("Dark")
                        .foregroundColor(.white)
                })
                .frame(width: 80, height: 40)
                .background(Color.black)
            } //: VSTACK
        } //: ZSTACK
        .edgesIgnoringSafeArea(.all)
        // When added here, the buttons are not blurred properly.
        .modifier(
             BlurModifier(
                 showBlur: $isPressed, blurColor: $blurColor
             )
        )
    }
    
    private func getSelectedBlurTitle() -> String {
        guard isPressed else { return "Clear"}
        switch blurColor {
        case .none:
            return "Default"
        case .light:
            return "Light"
        case .dark:
            return "Dark"
        }
    }
}

struct BlurViewDemo_Previews: PreviewProvider {
    static var previews: some View {
        BlurViewDemo()
    }
}

视图修改器

public enum BlurColor {
    case none
    case light
    case dark
}

import SwiftUI

struct BlurModifier: ViewModifier {
    @Binding private var showBlur: Bool
    @Binding private var blurColor: BlurColor
    @State private var blurRadius: CGFloat = 14
    
    public init(showBlur: Binding<Bool>, blurColor: Binding<BlurColor>) {
        self._showBlur = showBlur
        self._blurColor = blurColor
    }
    
    func body(content: Content) -> some View {
        ZStack {
            content
                .blur(radius: showBlur ? blurRadius : 0, opaque: true)
                .animation(Animation.easeInOut(duration: 0.3))
            
            .edgesIgnoringSafeArea(.all)
            .navigationBarHidden(showBlur ? true : false)
            Rectangle()
                .fill(showBlur ? getBlurColor() : Color.white.opacity(0.0001))
                .edgesIgnoringSafeArea(.all)
        }
    }
    
    private func getBlurColor() -> Color {
        switch blurColor {
        case .none:
            return Color.white.opacity(0.5)
        case .light:
            return Color.white.opacity(0.6)
        case .dark:
            return Color.black.opacity(0.5)
        }
    }
}
swift swiftui overlay blur viewmodifier
1个回答
0
投票

您应该通过将视图修改器中的不透明参数设置为 false 来禁用它,如下所示:

.blur(radius: showBlur ? blurRadius : 0, opaque: false)
© www.soinside.com 2019 - 2024. All rights reserved.