Reputation: 13085
I'm trying to create a view composed of two parts - the top part is an image with a piece of text overlaid in the top left corner. The top part should take up 2/3 of the height of the view. The bottom part is text information and a button, contained in an HStack, and takes up the remaining 1/3 of the view height.
struct MainView: View {
var body: some View {
GeometryReader { gr in
VStack(spacing: 0) {
ImageInfoView()
.frame(height: gr.size.height * 0.66)
BottomInfoView()
}
.clipShape(RoundedRectangle(cornerRadius: 20))
}
}
}
struct ImageInfoView: View {
var body: some View {
ZStack(alignment: .topLeading) {
Image("testImage")
.resizable()
.aspectRatio(contentMode: .fill)
.overlay(Rectangle()
.fill(Color.black.opacity(0.5))
)
HStack {
Text("Top left text")
.foregroundColor(.white)
.padding()
}
}
}
}
struct BottomInfoView: View {
var body: some View {
HStack {
VStack(alignment:.leading) {
Text("Some title")
Text("Some subtitle")
}
Spacer()
Button("BUTTON") {
}
}
.padding()
.background(.gray)
}
}
In the below sample code, if I set the frame height to 400 I will see the top left text, but when I set it to 200, I do not. What is happening here? The text should be anchored to the top left corner of ImageInfoView no matter what. Further, when set to 400, why does the ImageInfoView take up more than 66% of the height?
struct TestView: View {
var body: some View {
MainView()
.frame(height: 200)
.padding([.leading, .trailing], 16)
}
}
Upvotes: 2
Views: 1416
Reputation: 13085
This fixes the problem:
ZStack(alignment: .topLeading) {
GeometryReader { gr in
Image("testImage")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(maxWidth: gr.size.width, maxHeight: gr.size.height)
.overlay(Rectangle()
.fill(Color.black.opacity(0.5))
)
HStack {
Text("Top left text")
.foregroundColor(.white)
.padding()
}
}
}
}
Upvotes: 0
Reputation: 258097
An image's fill
pushes ZStack
boundaries, so Text goes off screen (see this for details).
A possible solution is to put image into overlay of other container so it respects provided space instead of imposing own.
Tested with Xcode 13.4 / iOS 15.5
ZStack(alignment: .topLeading) {
Color.clear.overlay( // << here !!
Image("testImage")
.resizable()
.aspectRatio(contentMode: .fill)
.overlay(Rectangle()
.fill(Color.black.opacity(0.5))
)
)
// ... other code as-is
Upvotes: 4