I'm new to SwiftUI and I'm trying to implement a card :
I want the image to be 124 units tall. Everything works fine until I try to add scaledToFill()
to the Image.
Here is my code:
var body: some View {
VStack {
Spacer()
VStack (spacing: 0) {
Image(uiImage: Asset.Assets.licencePerksBannerCover.image)
.resizable()
// .scaledToFill()
.frame(height: 124)
Text("Title")
}
.background(Color.white)
Spacer()
}
.padding()
.background(Color.green)
}
This is what it looks like without when scaledToFill()
is commented:
As you can see, the image is stretched, but the card itself respects the padding that I've given to the main VStack.
This is what it looks like when I uncomment scaledToFill()
:
The image doesn't stretch anymore but now the card takes the entire width of the phone.
If I also give a width of 50 to the Image, the main green stack becomes 50 units wide as expected, but the image still takes all the width of the phone:
var body: some View {
VStack {
Spacer()
VStack (spacing: 0) {
Image(uiImage: Asset.Assets.licencePerksBannerCover.image)
.resizable()
.scaledToFill()
.frame(width: 50, height: 124)
Text("Title")
}
.background(Color.white)
Spacer()
}
.padding()
.background(Color.green)
}
I don't understand why scaledToFill()
makes the image take the entire width of the screen. I couldn't find any explanation online on the reason it does this and how to fix it.
The modifier .scaledToFill()
causes the image to overflow the frame you are setting, so it needs to be clipped. If it is not clipped, the overflow remains visible.
If you only know one dimension of the frame (the height in this case), then you can use a greedy view such as a Color
to fill the available space. The image can then be shown as an overlay and clipped:
VStack (spacing: 0) {
Color.clear
.frame(height: 124)
.overlay {
Image(uiImage: Asset.Assets.licencePerksBannerCover.image)
.resizable()
.scaledToFill()
}
.clipped()
Text("Title")
}
.background(Color.white)
Looking at your first image, I am wondering whether in fact you might want to be using scaledTofit
for wide images, instead of scaledToFill
? If you are not sure whether an image will be wide or tall then you can use ViewThatFits(in: .horizontal)
to try scaledToFill
first, followed by scaledToFit
as fallback. The answer to Image is being rendered with 1/3 of screen width shows how.