8

enter image description here

I want to make the highlighted section transparent and blurred similar to other macOS applications. I found articles online on how to use an NSViewController to blur which I don't fully understand. I am new to swift and don't yet understand how to use Viewcontrollers. My code is below. Any help would be appreciated!


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()
    }
}


Andy Jazz
  • 49,178
  • 17
  • 136
  • 220
Kushagra
  • 103
  • 2
  • 7

2 Answers2

15

You don't really need to subclass NSViewController. What you need is - NSVisualEffectView from AppKit,

A view that adds translucency and vibrancy effects to the views in your interface.

Since the NSVisualEffectView is not yet available in SwiftUI, you can wrap it using NSViewRepresentable pretty much like every AppKit control not available in SwiftUI.

You can do it like this -

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
    }
}

You can then use it as a standalone View-

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

or use it as a background modifier to your highlighted VStack like this -

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

Go through the Apple Developer docs to learn more about the two blending modes. Also, play with the Material property to get the desired result.

Peter Schorn
  • 916
  • 3
  • 10
  • 20
AnaghSharma
  • 404
  • 4
  • 14
0

This solution allows you to create a semiOpaqueWindow() type method that you can apply to a child of the View protocol, for example to a Rectangle shape here.

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")
        }
    }
}
Andy Jazz
  • 49,178
  • 17
  • 136
  • 220