I need view A to be centered on the screen (vertically and horizontally). I need view B to appear 30px below view A, also centered horizontally. But A must remain in the center of the screen, without moving upward when B is added. I can accomplish most of this by using .overlay
and GeometryReader
:
struct ContentView: View {
var body: some View {
VStack {
ZStack {
Rectangle()
.fill(.red)
.frame(width: 200, height: 100)
.overlay {
GeometryReader {geo in
Rectangle()
.fill(.blue)
.frame(width: 100, height: 100)
.offset(y: geo.size.height + 30)
}
}
}
}
}
}
I don't know how to center the blue Rectangle horizontally though. I don't necessarily know its width, although it's specified here for visual purposes. Assuming I don't know the exact frame values for either view, how I can I position B 30px below A while keeping A in the center of the screen? And is there a better view structure for accomplishing this?
You could just use a VStack
with a hidden copy of the blue rectangle above the red one:
struct ContentView: View {
private var blueRectangle: some View {
Rectangle()
.fill(.blue)
.frame(width: 100, height: 100)
}
var body: some View {
VStack(spacing: 30) {
blueRectangle.hidden()
Rectangle()
.fill(.red)
.frame(width: 200, height: 100)
blueRectangle
}
}
}
Alternatively, if the blue rectangle is not expected to be wider than the red one then here's how you could do it with an overlay:
var body: some View {
Rectangle()
.fill(.red)
.frame(width: 200, height: 100)
.overlay(alignment: .top) {
GeometryReader { proxy in
blueRectangle
.frame(maxWidth: proxy.size.width)
.fixedSize(horizontal: false, vertical: true)
.offset(y: proxy.size.height + 30)
}
}
}