swiftswiftui

How can I make an image 100 percent the width of its container in SwiftUI?


I have users uploading images from their mobile device and these images can be either are portrait or landscape. I have these images tiled similar to Instagram posts. The biggest problem I'm having is that portrait images are not rendering at 100 percent of the container width. It's really bizarre.

Here is an example of a "portrait" photo taken by me and visualized using the following code:

VStack{
    AnimatedImage(url: URL(string: self.mediaLink))
        .resizable()
        .aspectRatio(contentMode: .fit)
        .frame(width: UIScreen.main.bounds.width - 40)
}
.padding(.horizontal, 20)
.frame(width: UIScreen.main.bounds.width - 40)

Even though I am specifying the width, it still renders incorrectly. It should be UIScreen.main.bounds.width - 40, which is the same width as its parent VStack

enter image description here

When using GeometryReader, my code looks like this:

GeometryReader{geo in
    VStack{
        AnimatedImage(url: URL(string: self.mediaLink))
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(width: geo.size.width)
    }
}
.frame(width: UIScreen.main.bounds.width)

Which is worse!

enter image description here

Any help is appreciated! Using .fill for the aspect ratio makes the images too large and they block everything in the card. The below code does not use GeometryReader

VStack{
    AnimatedImage(url: URL(string: self.mediaLink))
        .resizable()
        .aspectRatio(contentMode: .fill)
        .frame(width: UIScreen.main.bounds.width - 40)
}
.frame(width: UIScreen.main.bounds.width - 40)

enter image description here


Solution

  • Tested your code with just Image("some_image") as below and it works (Xcode 12 / iOS 14), so the issue is either in AnimatedImage or in some other code.

    VStack{
        Image("some_image")
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(width: UIScreen.main.bounds.width - 40)
    }
    .padding(.horizontal, 20)
    .frame(width: UIScreen.main.bounds.width - 40)