如何在SwiftUI macOS应用程序中模糊背景?

ercv8c1e  于 2023-02-18  发布在  Swift
关注(0)|答案(2)|浏览(215)

我想让高亮显示的部分变得透明和模糊,类似于其他macOS应用程序。我在网上找到了一些关于如何使用NSViewController来模糊的文章,但我并不完全理解。我是swift的新手,还不知道如何使用Viewcontroller。我的代码如下。如有任何帮助,将不胜感激!

import SwiftUI

struct ContentView: View {

    var body: some View {
        VStack {
            GeometryReader { geometry in
                NavigationView{
                    HStack(spacing: 0) {
                        ZStack{

                            Text("BitMessenger")
                                .font(.title)
                                .fontWeight(.light)
                                .foregroundColor(Color.white)
                        }
                        .frame(width: geometry.size.width/2, height: geometry.size.height+20)
                        .background(Color(red: 0.07, green: 0.07, blue: 0.07, opacity: 1.0))
                        VStack{

                            HStack {
                                Text("Sign Up")
                                    .font(.headline)
                                    .padding(.top, 30.0)
                                Spacer()
                            }



                            HStack {
                                Text("Welcome to BitMessenger")
                                    .font(.subheadline)
                                    .foregroundColor(Color.gray)
                                    .padding(.top, 10.0)
                                Spacer()
                            }

                            Form {
                                VStack{
                                    HStack {
                                        Text("Full Name")
                                            .font(.caption)
                                            .foregroundColor(Color.white)
                                            .padding(.top, 10.0)
                                        Spacer()
                                    }



                                    TextField("ex. John Doe", text: /*@START_MENU_TOKEN@*//*@PLACEHOLDER=Value@*/.constant("")/*@END_MENU_TOKEN@*/)



                                    HStack {
                                        Text("Email Address")
                                            .font(.caption)
                                            .foregroundColor(Color.white)
                                            .padding(.top, 10.0)
                                        Spacer()
                                    }



                                    TextField("doejohn@example.com", text: /*@START_MENU_TOKEN@*//*@PLACEHOLDER=Value@*/.constant("")/*@END_MENU_TOKEN@*/)



                                    HStack {
                                        Text("Password")
                                            .font(.caption)
                                            .foregroundColor(Color.white)
                                            .padding(.top, 10.0)
                                        Spacer()
                                    }


                                    TextField("AIOFHWaowhf", text: /*@START_MENU_TOKEN@*//*@PLACEHOLDER=Value@*/.constant("")/*@END_MENU_TOKEN@*/)

                                    HStack {
                                        Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/) {
                                            Text("Register")
                                                .padding(.horizontal, 10.0)
                                        }
                                        .padding(.all)
                                    }

                                }
                            }
                            .padding(.top)

                            Spacer()

                            NavigationLink(destination: ContentView()) {
                                Text("Already have an Account? Login")
                                .font(.caption)
                                    .foregroundColor(Color.gray)
                                    .background(Color.clear)
                            }
                            .padding(.bottom)
                            .foregroundColor(Color.clear)

                        }
                        .padding(.horizontal, 30.0)
                        .frame(width: geometry.size.width / 2, height: geometry.size.height+20)
                        .background(Color.black.opacity(0.9))
                    }.edgesIgnoringSafeArea(.all)
                }

            }
            .edgesIgnoringSafeArea(.all)
            .frame(width: 750.0, height: 500.0)

        }

    }
}

class MyViewController: NSViewController {

    var visualEffect: NSVisualEffectView!

    override func loadView() {
        super.loadView()

        visualEffect = NSVisualEffectView()
        visualEffect.translatesAutoresizingMaskIntoConstraints = false
        visualEffect.material = .dark
        visualEffect.state = .active
        visualEffect.blendingMode = .behindWindow
        view.addSubview(visualEffect)

        visualEffect.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        visualEffect.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        visualEffect.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        visualEffect.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
i5desfxk

i5desfxk1#

您实际上不需要子类化NSViewController,您需要的是AppKit中的-NSVisualEffectView
为界面中的视图添加半透明和活力效果的视图。
由于NSVisualEffectView在SwiftUI中尚不可用,您可以使用NSViewRepresentable Package 它,就像SwiftUI中不可用的每个AppKit控件一样。
你可以这样做-

import SwiftUI

struct VisualEffectView: NSViewRepresentable
{
    let material: NSVisualEffectView.Material
    let blendingMode: NSVisualEffectView.BlendingMode
    
    func makeNSView(context: Context) -> NSVisualEffectView
    {
        let visualEffectView = NSVisualEffectView()
        visualEffectView.material = material
        visualEffectView.blendingMode = blendingMode
        visualEffectView.state = NSVisualEffectView.State.active
        return visualEffectView
    }

    func updateNSView(_ visualEffectView: NSVisualEffectView, context: Context)
    {
        visualEffectView.material = material
        visualEffectView.blendingMode = blendingMode
    }
}

然后可以将其用作独立的View-

VisualEffectView(material: NSVisualEffectView.Material.contentBackground, blendingMode: NSVisualEffectView.BlendingMode.withinWindow)

或者用它作为背景修饰符来修饰高亮显示的VStack,就像这样-

.background(VisualEffectView(material: NSVisualEffectView.Material.contentBackground, blendingMode: NSVisualEffectView.BlendingMode.withinWindow))

浏览Apple Developer文档来学习更多关于这两种混合模式的知识。另外,使用Material属性来获得想要的结果。

8hhllhi2

8hhllhi22#

这个解决方案允许您创建一个semiOpaqueWindow()类型的方法,您可以将其应用于View协议的子协议,例如这里的Rectangle形状。

import SwiftUI

extension View {
    public static func semiOpaqueWindow() -> some View {
        VisualEffect().ignoresSafeArea()
    }
}

struct VisualEffect : NSViewRepresentable {
    func makeNSView(context: Context) -> NSView {
        let view = NSVisualEffectView()
        view.state = .active
        return view
    }
    func updateNSView(_ view: NSView, context: Context) { }
}
struct ContentView : View {
    var body: some View {
        ZStack {
            Rectangle.semiOpaqueWindow()
            Text("Semi Transparent MacOS window")
        }
    }
}

相关问题