Reputation: 5391
I want to achieve the following constraint-based layout of images in a SwiftUI
List
:
Image
to the list margins (adapts to screen size)What I have tried and doesn't work (based on this article):
struct MyView: View {
@ObservedObject var viewModel: MyViewModel
let aspectRatio = CGSize(width: 345, height: 120)
var body: some View {
List {
ForEach(viewModel.items) { item in
GeometryReader { geo in
Image("test_image")
.resizable()
.aspectRatio(aspectRatio, contentMode: .fill)
.frame(width: geo.size.width)
.clipped()
}
}
}
}
}
The size I get from geo
is (343, 32) on iPhone 11 Pro. Width makes sense but it's not letting the cells expand beyond a height of 32 for some reason. Any tips welcome because I'm really starting to miss auto layout constraints.
Upvotes: 1
Views: 935
Reputation: 30426
No need to use GeometryReader
for something like this. For the fixed height, you can just supply a frame
with height
only. You also don't need to create your own let aspectRatio = CGSize(width: 345, height: 120)
- if you leave it nil (by default) it should be fine.
Edit: Using padding
instead of VStack
with spacing
struct MyView: View {
var body: some View {
List {
ForEach(0..<10, id: \.self) { item in
Image("test_image")
.resizable()
.aspectRatio(contentMode: .fill) /// no need for custom aspect ratio
.frame(height: 120) /// fixed height of image
.clipped() /// stop image from overflowing
.padding(.vertical, 12) /// extra vertical padding
}
}
}
}
Result (with "test_image"):
However, this has a fixed height of 120
, so the top and bottom of the images are cropped out. To fix this, you can just avoid frame
and clipped
altogether.
struct MyView: View {
var body: some View {
List {
ForEach(0..<10, id: \.self) { item in
Image("test_image")
.resizable()
.aspectRatio(contentMode: .fill) /// doesn't matter if it's fit or fill
.padding(.vertical, 12) /// extra vertical padding
}
}
}
}
Result:
Upvotes: 1