3

How I can make a square image similar to the photo gallery?

I'm trying the following:

let columns: [GridItem] = [
  GridItem(.flexible()),
  GridItem(.flexible())
]

LazyVGrid(
    columns: columns,
    alignment: .center
) {
    ForEach(self.selectedImages, id: \.self) { image in
        Image(uiImage: image)
            .resizable()
            .scaledToFit()
            .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
            .aspectRatio(1, contentMode: .fill)
            .background(Color.blue)
    }
}

However, this results in this:

enter image description here

I want to build a 2x2 square grid (similar to this 3x3 below - I want the images to fit nicely into the square)

enter image description here

user1354934
  • 8,139
  • 15
  • 50
  • 80
  • Does this answer your question https://stackoverflow.com/a/63027052/12299030? – Asperi Oct 19 '20 at 04:04
  • Actually that did not worked for me :( It works if I use a geometryReader to set a width and height, but that seems kind of much right? – user1354934 Oct 19 '20 at 05:09

2 Answers2

18

Try this. It provides the correct aspect ratio and properly clips the images to fill a square:

ForEach(self.selectedImages, id: \.self) { image in
    Color.blue
        .aspectRatio(1, contentMode: .fill)
        .overlay(
            Image(uiImage: image)
                .resizable()
                .scaledToFill()
        ).clipped()
}
vacawama
  • 150,663
  • 30
  • 266
  • 294
  • Thanks for this. I was struggling to keep `AsyncImage`s square in my `LazyVGrid` and wrapping it in a Color like this seems a better workaround than the alternatives I've seen that invoke combinations of `GeometryReader` and frame manipulation. Feels like it should be a simple configuration to force an aspect ratio in a LazyXGrid layout so I worry I'm misusing the view somehow. But that is now a concern for a slower day. – Nathan Hosselton Oct 11 '22 at 16:47
  • This answer works but what's actually going on here? Is there some magic to the color blue? Can it be another view? – erotsppa Mar 02 '23 at 03:52
  • The `Color.blue` just serves as the base view and provides the frame for the image. The color doesn't matter since it will be overlayed by the image. I usually use `Color.clear`. `.scaledToFill()` will cause some of the image to go outside of the `Color.blue` square, and `.clipped()` removes that overhang. – vacawama Mar 02 '23 at 04:02
1

I found this to be effective:

Image(uiImage: image)
            .resizable()
            .aspectRatio(1, contentMode: .fill)
            .clipped()

when used with a LazyVGrid and a columns value of

let columns = [GridItem(.adaptive(minimum: 80))]
P. Ent
  • 1,654
  • 1
  • 12
  • 22