如何在 SwiftUI 中居中裁剪图像

Ren*_*ade 10 image center crop ios swiftui

我是 SwiftUI 的新手。我想每个人都在这一点上。我已经做了大约 6 年的应用程序开发人员,我觉得在 StackOverflow 上问这个问题很愚蠢。但我到处看。如何在 SwiftUI 的 ImageView 中居中裁剪图像?

我知道有一个选项可以更改纵横比,但我只看到适合和填充。我只是想让 imageView 居中裁剪(android 术语)图像。有人知道吗?

vac*_*ama 31

Android 的ImageView.ScaleType文档描述CENTER_CROP为:

CENTER_CROP

均匀缩放图像(保持图像的纵横比),使图像的两个尺寸(宽度和高度)等于或大于视图的相应尺寸(减去填充)。然后图像在视图中居中。

这基本上就是Aspect Fill Scaling (aka .scaledToFill()) 所做的,除了(令人惊讶的是)Aspect Fill不会剪辑掉在框架之外的部分。

通过制作图像.resizable,并应用.scaledToFill(). 图像将按比例缩放以填充其可用框架,必要时不保留顶部和底部或侧面。 .clipped()然后删除帧外的图像部分。

Image("myImage")
    .resizable()
    .scaledToFill()
    .frame(width: 200, height: 200, alignment: .center)
    .clipped()
Run Code Online (Sandbox Code Playgroud)

为了使这个更方便,我创造了这个extensionImage

extension Image {
    func centerCropped() -> some View {
        GeometryReader { geo in
            self
            .resizable()
            .scaledToFill()
            .frame(width: geo.size.width, height: geo.size.height)
            .clipped()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

要使用Image extension,只需将它放在项目中的文件中(像这样的名称image-centercropped.swift会很好地工作)。然后只需添加.centerCropped()到您想要居中裁剪的任何图像。

Image("apolloimage").centerCropped()
Run Code Online (Sandbox Code Playgroud)

它用于GeometryReader确定其框架,以便它可以正确裁剪图像,这意味着不必指定框架即可获得正确的剪裁。您可以使用显式框架随意调整图像的大小,或者只是添加padding()Spacer()保持它相对于其他用户界面项目的良好放置。

例如:如果您想要一个图像填满手机的屏幕:

struct ContentView: View { 
    var body: some View {
        Image("apolloimage")
            .centerCropped()
            .edgesIgnoringSafeArea(.all)
    }
}
Run Code Online (Sandbox Code Playgroud)

通过缩放图像以显示图像的全高或全宽,并在另一个维度上裁剪悬垂的部分,将很好地显示图像的中心。


示范:

这是一个演示,展示了图像如何随着图像的增长而居中和裁剪。在此演示,框架宽度是恒定的360,而帧的高度从变化50700随着滑块前进到右侧。一开始当帧很短时,图像的顶部和底部被裁剪。当帧超过原始图像的纵横比时,生成的图像居中但在左右两侧被裁剪。

struct ContentView: View {
    
    @State private var frameheight: CGFloat = 50
    
    var body: some View {
        VStack(spacing: 20) {
            Spacer()
            Image("apolloimage")
                .resizable()
                .scaledToFill()
                .frame(width: 360, height: self.frameheight)
                .clipped()
            Spacer()
            Slider(value: self.$frameheight, in: 50...700)
                .padding(.horizontal, 20)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

或使用以下等效测试.centerCropped()

struct ContentView: View {
    
    @State private var frameheight: CGFloat = 50
    
    var body: some View {
        VStack(spacing: 20) {
            Spacer()
            Image("apolloimage")
                .centerCropped()
                .frame(width: 360, height: self.frameheight)
            Spacer()
            Slider(value: self.$frameheight, in: 50...700)
                .padding(.horizontal, 20)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在 .centerCropped 缩放模拟器上运行的演示


替代解决方案

使中心的另一种方式裁剪图像,使图像的.overlay()Color.clear。这允许Color.clear建立剪辑边界。

Color.clear
.overlay(
    Image("apolloimage")
    .resizable()
    .scaledToFill()
)
.clipped()
Run Code Online (Sandbox Code Playgroud)

和对应extensionImage看起来像这样:

extension Image {
    func centerCropped() -> some View {
        Color.clear
        .overlay(
            self
            .resizable()
            .scaledToFill()
        )
        .clipped()
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 再看看。使用我提供的“Image”“extension”。您不必指定框架。只需使用`Image("imageName").centerCropped()`。我什至向您展示如何让它填满手机屏幕,而且无需指定框架。 (3认同)

小智 7

我能够像 iPhone 照片应用程序一样裁剪图像的方形中心以供查看。

extension Image {
    func centerSquareCropped() -> some View {
        GeometryReader { geo in
            let length = geo.size.width > geo.size.height ? geo.size.height : geo.size.width
            self
                .resizable()
                .scaledToFill()
                .frame(width: length, height: length, alignment: .center)
                .clipped()
        }
    }
 }
Run Code Online (Sandbox Code Playgroud)