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

4

8

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

Commissary answered 17/8, 2020 at 22:20 Comment(3)
Tested your code with just Image("some_image") and it works, so the issue is either in AnimatedImage or in some other code.Wilek
If you check the preview of the complete view in your canvas, do you see the width of the VStack being the same as the image for the first example you wrote? It might be something related to the height, as experiment have you tried fixing the height to something close to the image expected height?Singlehandedly
@Wilek is correct. The problem is with AnimatedImage. I'm using this dependency for my project. github.com/SDWebImage/SDWebImageSwiftUI. All I had to do was change AnimatedImage to WebImage. If you post, I'll mark as answered. :)Commissary
W
5

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)
Wilek answered 18/8, 2020 at 14:23 Comment(0)
P
1

Try to use scaledToFill and clipped modifiers

    VStack{
        AnimatedImage(url: URL(string: self.mediaLink))
            .resizable()
            .scaledToFill()
            .frame(width: UIScreen.main.bounds.width - 40)
            .clipped()
    }
    .frame(width: UIScreen.main.bounds.width - 40)
Plover answered 18/8, 2020 at 8:42 Comment(0)
G
0

I think this change will help you:

VStack {
    AnimatedImage(url: URL(string: self.mediaLink))
       .resizable()
       .scaledToFit()
}
.frame(width: UIScreen.main.bounds.width - 40)
Garfieldgarfinkel answered 18/8, 2020 at 8:11 Comment(0)
E
0

All of these answers use UIScreen.main.bounds.width, which is a bad idea.

What if the view is in a form sheet, or used inside a sidebar layout on the iPad? What if the size of the container changes after you set it up? Using a fixed numeric size like that is going to cause problems.

Instead, use the containerRelativeFrame modifier:

      Image("some_image")
        .resizable()
        .scaledToFit()
        .containerRelativeFrame(.horizontal)  { width, axis in
          width
        }

This will set the width of the image to the exact width of its container, and will even update as the container's size changes.

This requires iOS 17, but even if you have to support older versions, you can use GeometryReader to achieve the same thing with a little more boilerplate.

Evaluate answered 29/9 at 14:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.