I'm trying to create an AsyncImage
with a placeholder image. With the following constraints...
- The placeholder image may not have the same aspect ratio as the
AsyncImage
. - The remote image may not have the same aspect ratio as the
AsyncImage
. - The remote and placeholder image may not have the same aspect ratios.
- The aspect ratio of the
AsyncImage
is fixed.
The requirements...
- The placeholder and the remote image must be scaled to fill the aspect ratio of the
AsyncImage
. - They must not be squashed.
- They must be clipped so that they do not overflow the bounds of the
AsyncImage
(set by the aspect ratio).
In my head this should be simple.
But I just cannot get this to work without at least one of the requirements breaking.
This is the closest I've got so far but the AsyncImage
is just not clipped so overflows beyond either the height or width.
You can paste this into Xcode and it will show the
import SwiftUI
let aspect = 1.5
struct TestView: View {
var body: some View {
AsyncImage(
url: URL(string: "https://placekitten.com/1920/1080"),
transaction: .init(animation: .easeIn(duration: 3)) // <- slow animation to show issue
) { phase in
switch phase {
case .success(let image):
image
.resizable()
.scaledToFill()
.aspectRatio(aspect, contentMode: .fill)
.clipped()
default:
Image(systemName: "rectangle")
.resizable()
.scaledToFill()
.aspectRatio(aspect, contentMode: .fill)
.clipped()
.foregroundColor(.white)
}
}
.aspectRatio(aspect, contentMode: .fill)
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
VStack {
TestView()
.overlay {
// This overlay shows the correct rect but the image is just not cclipped.
Color.black
.opacity(0.5)
.aspectRatio(aspect, contentMode: .fit)
}
.padding()
.aspectRatio(aspect, contentMode: .fit)
}
.background(Color.red)
.padding()
}
}
This gives me the following...
The red background is from the VStack. The black transparent overlay shows the aspect ratio I'm looking for based on the aspect
set at the top of the file.
have you tried using a geometry reader to set the height and width of the image container?
You can use this to work out the required ratio. That's the approach I would take.