I am trying to guarantee that regardless of the image's dimensions, it won't overlap its neighbor sitting above it vertically.
Here is the code I used.
import SwiftUI
struct CardDetailView: View {
var body: some View {
ZStack {
Color.black
.edgesIgnoringSafeArea(.all)
Image(.darkColorShade)
.resizable()
.edgesIgnoringSafeArea(.all)
ScrollView {
VStack {
Text("Two of Cups".capitalized)
.font(.largeTitle)
.foregroundColor(.white)
// Spacer(minLength: 100)
Image(uiImage: .cardDemo)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 170, height: 150)
}
}
}
}
}
struct CardDetailView_Previews: PreviewProvider {
static var previews: some View {
CardDetailView()
}
}
When I uncomment the Spacer, it adjusts to the location I want. The Image should appear vertically below the text because it comes after the text in a VStack
.
When the spacer is commented, the image overlaps its neighbor if its frame width exceeds its height. Why is that?
I am just trying to produce a predictable and reliable space between two different views. I shouldn't just tweak it to appear correct without understanding what is happening. I also tried setting the background of Image View to red, but that didn't give me any clues to what was happening.
CodePudding user response:
Why does Image overlap the view above it in a SwiftUI VStack?
The image is overflowing its frame. Notice that your frame is wider than it is tall:
Image(uiImage: .cardDemo)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 170, height: 150)
But it doesn’t look that way onscreen. The image is oozing over the top and bottom of the frame. This is what .aspectRatio(contentMode: .fill)
does. It scales the original image proportionally until it fills the frame in each direction overflowing the frame in one direction if necessary.
If you add:
.clipped()
It will clip the parts that fall outside of the frame. Then it will not overlap the objects above it and below it.
How can I ensure the image maintains a certain width and height proportion?
Use .aspectRatio(contentMode: .fit)
or .scaledToFit()
along with a frame
that specifies only the width
or the height
. SwiftUI will calculate the other dimension of the frame
to maintain the image proportions (aspect ratio).
Image(uiImage: .cardDemo)
.resizable()
.scaledToFit()
.frame(width: 170)
CodePudding user response:
Using a spacer will try to use all of the space given to that view. My best fix for this would be to manually put a specific amount of padding. For example, under the Image(uiImage: .cardDemo)
you could put .padding(.top, 75)
, and that would add some space between Two of Cups
.
Hope I helped :)