SwiftUI 中的透明和模糊 fullScreenCover 模态?

Posted

技术标签:

【中文标题】SwiftUI 中的透明和模糊 fullScreenCover 模态?【英文标题】:Transparent and Blurred fullScreenCover modal in SwiftUI? 【发布时间】:2021-01-29 15:17:59 【问题描述】:

我是在我的 SwiftUI 项目中显示模式的 fullScreenCover。

但是,我需要以透明和模糊的背景显示模态框。

但我似乎根本无法做到这一点。

这是我的代码:

.fullScreenCover(isPresented: $isPresented) 
                       VStack(spacing: 20) 
                           Spacer()
                               .frame(maxWidth: .infinity, minHeight: 100)
                               .background(Color.black)
                               .opacity(0.3)
                           
                           //Text("modal")
                       
                       .background(SecondView())     // << helper !!
                   

我在同一个视图上有这个:

struct BackgroundBlurView: UIViewRepresentable 
    func makeUIView(context: Context) -> UIView 
        let view = UIVisualEffectView(effect: UIBlurEffect(style: .light))
        DispatchQueue.main.async 
            view.superview?.superview?.backgroundColor = .clear
        
        return view
    

    func updateUIView(_ uiView: UIView, context: Context) 

上面的代码将打开全屏模式,但它根本不透明或模糊。

这是我得到的:

我还有什么需要做的吗?

我从哪里获得上述代码的参考:

SwiftUI: Translucent background for fullScreenCover

【问题讨论】:

【参考方案1】:

我删除了一些无关的东西,并确保背景中有你可以看到的内容。

如果没有其他答案中建议的alpha,效果会非常微妙,但确实存在。

struct ContentView : View 
    @State var isPresented = false
    
    var body: some View 
        VStack 
            Text("Some text")
            Spacer()
            Text("More")
            Spacer()
            Button(action: 
                isPresented.toggle()
            ) 
                Text("Show fullscreenview")
            
            .fullScreenCover(isPresented: $isPresented) 
                Text("modal")
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(BackgroundBlurView())
            
            Spacer()
            Text("More text")
        
        
    


struct BackgroundBlurView: UIViewRepresentable 
    func makeUIView(context: Context) -> UIView 
        let view = UIVisualEffectView(effect: UIBlurEffect(style: .light))
        DispatchQueue.main.async 
            view.superview?.superview?.backgroundColor = .clear
        
        return view
    

    func updateUIView(_ uiView: UIView, context: Context) 


注意你可以从Button 中看到的非常微妙的蓝色。在深色模式下更明显。

当您向背景视图添加更多颜色和内容时,效果可能会变得更加生动。不过,添加alpha 肯定会让事情变得更加明显。

【讨论】:

【参考方案2】:

@Asperi 回答 from here 是完全正确的。只需要添加 alpha 来模糊视图。

struct BackgroundBlurView: UIViewRepresentable 
    func makeUIView(context: Context) -> UIView 
        let view = UIVisualEffectView(effect: UIBlurEffect(style: .light))
        view.alpha = 0.5 //< --- here
        DispatchQueue.main.async 
            view.superview?.superview?.backgroundColor = .clear
        
        return view
    
    
    func updateUIView(_ uiView: UIView, context: Context) 


另一种方法是使用 ViewControllerHolder reference link

struct ViewControllerHolder 
    weak var value: UIViewController?


struct ViewControllerKey: EnvironmentKey 
    static var defaultValue: ViewControllerHolder 
        return ViewControllerHolder(value: UIApplication.shared.windows.first?.rootViewController)
    


extension EnvironmentValues 
    var viewController: UIViewController? 
        get  return self[ViewControllerKey.self].value 
        set  self[ViewControllerKey.self].value = newValue 
    


extension UIViewController 
    func present<Content: View>(backgroundColor: UIColor = UIColor.clear, @ViewBuilder builder: () -> Content) 
        let toPresent = UIHostingController(rootView: AnyView(EmptyView()))
        toPresent.view.backgroundColor = backgroundColor
        toPresent.modalPresentationStyle = .overCurrentContext
        toPresent.modalTransitionStyle = .coverVertical
        toPresent.rootView = AnyView(
            builder()
                .environment(\.viewController, toPresent)
        )
        
        //Add blur efect
        let blurEfect = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
        blurEfect.frame = UIScreen.main.bounds
        blurEfect.alpha = 0.5
        toPresent.view.insertSubview(blurEfect, at: 0)
        self.present(toPresent, animated: true, completion: nil)
    

struct ContentViewNeo: View 
    @Environment(\.viewController) private var viewControllerHolder: UIViewController?
    
    var body: some View 
        VStack 
            Text("Background screen")
            Button("Open") 
                viewControllerHolder?.present(builder: 
                    SheetView()
                )
            
        
    


struct SheetView: View 
    var body: some View 
        Text("Sheet view")
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
    

【讨论】:

以上是关于SwiftUI 中的透明和模糊 fullScreenCover 模态?的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI - 如何模糊视图的默认背景颜色?

SwiftUI:函数声明了一个不透明的返回类型,但其主体中的返回语句没有匹配的底层类型

在jframe中的模糊背景上创建一个透明矩形

如何在 SwiftUI 中将模糊效果作为背景?

swift 4.2 ios 12中的状态栏模糊视图(半透明)

SwiftUI SecureField:如何实现与 UIKit 中相同的字符模糊行为?