🐕
【SwiftUI】ContentModeにfillが設定されたImageを正方形にトリミングする
正方形にトリミングされたImageの幅と高さは、基本的に親ビューから提案サイズの小さい方となります。
理想サイズが使用されるシチュエーションとしては、上下左右のスクロールに対応したScrollViewぐらいだと思います。

Image(uiImage: uiImage)
.resizable()
.scaledToFill()
.frame(minWidth: 0, idealWidth: 100, minHeight: 0, idealHeight: 100) // 重要
.aspectRatio(1, contentMode: .fit)
.clipped()
サンプル
struct ContentView: View {
@State private var uiImage: UIImage? = nil
@State private var index = 0
var body: some View {
Group {
if let uiImage {
content(uiImage)
} else {
ProgressView()
}
}
.task {
guard let url = URL(string: "https://picsum.photos/1920/1080") else { return print(1) }
guard let data = try? await URLSession.shared.data(from: url).0 else { return print(2) }
guard let uiImage = UIImage(data: data) else { return print(3) }
self.uiImage = uiImage
}
}
func image(_ uiImage: UIImage) -> some View {
Image(uiImage: uiImage)
.resizable()
.scaledToFill()
.frame(minWidth: 0, idealWidth: 100, minHeight: 0, idealHeight: 100)
.aspectRatio(1, contentMode: .fit)
.clipped()
}
func content(_ uiImage: UIImage) -> some View {
VStack {
Group {
switch index {
case 0: verticalStack(uiImage)
case 1: horizontalStack(uiImage)
case 2: verticalScrollView(uiImage)
case 3: horizontalScrollView(uiImage)
case 4: twoAxisScrollView(uiImage)
default: EmptyView()
}
}
.border(.primary)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
.safeAreaInset(edge: .bottom) {
Button("Next") {
index = (index + 1) % 5
}
}
}
func verticalStack(_ uiImage: UIImage) -> some View {
VStack {
image(uiImage)
}
.frame(width: 300, height: 500)
}
func horizontalStack(_ uiImage: UIImage) -> some View {
HStack {
image(uiImage)
}
.frame(width: 350, height: 200)
}
func verticalScrollView(_ uiImage: UIImage) -> some View {
ScrollView(.vertical) {
image(uiImage)
}
.frame(width: 300, height: 500)
}
func horizontalScrollView(_ uiImage: UIImage) -> some View {
ScrollView(.horizontal) {
image(uiImage)
}
.frame(width: 350, height: 200)
}
func twoAxisScrollView(_ uiImage: UIImage) -> some View {
ScrollView([.horizontal, .vertical]) {
image(uiImage)
}
.frame(width: 350, height: 200)
}
}
Discussion