Reputation: 992
I am currently facing an issue where I need to split a window into two sections, with transparent areas surrounding a text field. Although I have managed to implement a workaround, I believe it is not the ideal solution and I am seeking guidance on how to improve it.
The main problem with my current approach is that when I manually resize the window, the colors used to split the window also resize, which is not the desired behavior. Essentially, I want the transparency around the text field area to remain consistent regardless of window resizing.
Here are the key points:
Any suggestions, tips, or alternative approaches on how to achieve this desired behavior would be greatly appreciated. Thank you in advance for your assistance!
This is how it looks normal
And here is how I don't want it to look like
Here is my code:
import SwiftUI
struct ContentView: View {
@State private var textFieldContent = ""
var body: some View {
ZStack {
VisualEffectView()
GeometryReader { geometry in
VStack {
Rectangle()
.foregroundColor(Color(red: 0.1, green: 0.1, blue: 0.1)) // darker gray color
.frame(height: geometry.size.height / 1.16)
Rectangle()
.foregroundColor(.clear)
.frame(height: geometry.size.height * 2 / 3)
}
HStack {
TextField("Send a message", text: $textFieldContent)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
.background(Color.clear)
.cornerRadius(25)
.focusable(false)
.padding(.leading, 20) // Add padding to adjust the text field position
Spacer() // pushes the button to the side
Button(action: {
// Your action here
}) {
Text("Send")
.foregroundColor(.blue) // text color of the button
}
.buttonStyle(PlainButtonStyle()) // Removing button's default styling
.padding(.trailing, 20) // adds some padding to the right of the button
}
.padding(1)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
VStack {
HStack {
Spacer()
Button(action: {
// Your action here
}) {
Image(systemName: "gearshape")
.foregroundColor(.blue)
.padding()
}
.buttonStyle(PlainButtonStyle())
.padding(.trailing, 0) // Adjust the trailing padding to move the gear button to the right
.padding(.top, 0) // Adjust the top padding to move the gear button down
}
Spacer()
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
.padding(.trailing, 0) // Adjust the trailing padding of the gear button container
.padding(.top, 20) // Adjust the top padding of the gear button container
}
}
.edgesIgnoringSafeArea(.all)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct VisualEffectView: NSViewRepresentable {
func makeNSView(context: Context) -> NSVisualEffectView {
let view = NSVisualEffectView()
view.blendingMode = .behindWindow
view.state = .active
view.material = .underWindowBackground
return view
}
func updateNSView(_ nsView: NSVisualEffectView, context: Context) {
// No update code needed here for this example.
}
}
I tried using geometryReader
in hope that would do the trick, but I realize this is not the right way of doing it. I was expecting that the color would be in the same position all the time, even after rescaling the size of the window.
GeometryReader { geometry in
VStack {
Rectangle()
.foregroundColor(Color(red: 0.1, green: 0.1, blue: 0.1)) // darker gray color
.frame(height: geometry.size.height / 1.16)
Rectangle()
.foregroundColor(.clear)
.frame(height: geometry.size.height * 2 / 3)
}
Upvotes: 1
Views: 196
Reputation: 52347
The main issue right now is that you're trying to rely on GeometryReader
to make relative size View
s, but it seems that you really want a static size height for the TextField
and its background.
There are a number of ways to achieve the layout you're looking for. I generally lean towards using frame
s rather than Spacer
s, but that's just a matter of preference.
struct ContentView: View {
@State private var textFieldContent = ""
var body: some View {
ZStack {
VisualEffectView()
VStack {
VStack {
// Main content
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
.background(
Color(red: 0.1, green: 0.1, blue: 0.1)
)
.overlay(
Button(action: {
// Your action here
}) {
Image(systemName: "gearshape")
.foregroundColor(.blue)
.padding()
}
.buttonStyle(PlainButtonStyle()) // Removing button's default styling
.padding(.trailing, 20) // adds some padding to the right of the button
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
)
HStack {
TextField("Send a message", text: $textFieldContent)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
.background(Color.clear)
.cornerRadius(25)
.focusable(false)
.padding(.leading, 20) // Add padding to adjust the text field position
Button(action: {
// Your action here
}) {
Text("Send")
.foregroundColor(.blue) // text color of the button
}
.buttonStyle(PlainButtonStyle()) // Removing button's default styling
.padding(.trailing, 20) // adds some padding to the right of the button
}
.padding(1)
}
}
.edgesIgnoringSafeArea(.all)
}
}
Note that you could also get rid of the ZStack
and just add .background(VisualEffectView())
to the outer VStack
-- also just a matter of preference.
Upvotes: 0