I'm trying to display an image in the middle of the screen:
struct ContentView: View {
let items = ["A", "B", "C", "D", "E", "F", "G"]
var body: some View{
VStack {
ForEach(items, id: \.self) { item in
Text(item)
}
Spacer() // 3.
GeometryReader { geometry in
Image("image-300x1200")
.resizable() // 1.
}
Button("Action") {}
}
}
}
I want the image to:
- Fill the full width of the screen, and
- Vertically if height is more than available space, crop top and bottom to fill available space without push the other views above and below the image beyond screen, and
- If the image height is less than available height, stick it to the bottom view which is the button
So far I think I've achieved 1 and 2, just not sure what modifies I need for 2:
So the image is resized without keeping aspect ratio. If I add scaledToFill()
after resizable()
it goes beyond the bottom of screen:
Then I thought about using the space provided by geometry reader, like adding the following:
.aspectRatio(geometry.size.width / geometry.size.height, contentMode: .fill)
But it still doesn't work as it doesn't crop.
You can do:
.aspectRatio(contentMode: .fill)
makes the image expand to fill the entire available width. Note that we do not want it to also expand vertically to fill the entire available height, hence thefixedSize
modifier.Then,
maxHeight: geometry.size.height
gives it a frame with maximum available height. Note that when the height is too large, the image will exceed this frame, so it also needs to beclipped()
.alignment: .bottom
so that the image stays at the bottom of the frame when the height is less than the available height.