I'm trying to make a view which holds an image loaded asynchronously from a network request. Before the image loads, I want to show a placeholder view which has a fixed size. When the image loads, I want to replace this placeholder view with the image, scaled to fit inside the frame of the placeholder view, but then I want the parent view to shrink to match the size of this image. I can't figure out how to do this last part.
Right now, it looks like this:
struct ItemCell: View {
var body: some View {
Group {
CustomImageView(from: imageURL, placeholder: PlaceholderView(), config: { $0.resizable() })
.aspectRatio(contentMode: .fit)
.frame(minWidth: 0, maxWidth: 150, minHeight: 0, maxHeight: 190, alignment: .bottomLeading)
}.background(Color.red) // To show that the view isn't resizing properly
}
}
struct PlaceholderView: View {
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 3, style: .continuous)
.frame(width: 150, height: 190)
.foregroundColor(Color(.secondarySystemBackground))
Image(systemName: "globe")
.resizable()
.scaledToFit()
.frame(width: 50)
.foregroundColor(.secondary)
}
}
}
The CustomImageView is adapted from this article on loading images asynchronously. The ItemCells are placed in a horizontal ScrollView. When I test this, it:
- correctly displays the placeholder view before the image is loaded;
- resizes the image so it maintains its aspect ratio and fits inside the 150x190 frame, but has a weird animation where some of the images shrink and then expand back; also, some of the images seem to shrink too much;
- does not resize the parent view to match the size of the image properly, but instead retains the full original height and some (?) extra width on some cells.
These two problems are shown in the gif below, with blue images and a red background. Notice the extra height on the first and third cells, and the extra width on the second. Also, note that the first image ends up smaller than when it first loads, even though it fit inside the original 150x190 frame at first.
How can I fix these problems?

.fitand a fixed cell size, so you unless all of your images are 150x190 you are going to end up with some space around the image. Try putting yourCustomImageViewinHStack&VStackwith someSpacer()s so that there is the ability for the image view to shrink - Paulw11CustomImageViewshrink to match the size of its child view? It seems to do this already, but not fully (like how the second cell in the image doesn't stay the full width of 190, but there's still a small extra amount of space on the right. And it never does this w.r.t. the height. - ceyxGroupforVStack { Spacer() HStack { CustomImageCell() Spacer() } } ...to no avail. This just makes the images slightly smaller so there's always extra space on the top and right. Why does theGroup/VStack/etc have a fixed height? I thought that with SwiftUI, in the absence of a programmatically defined frame, the parent view adopts the size of the child view? - ceyx