在SwiftUI中将图像裁剪为正方形 [英] Clip image to square in SwiftUI

查看:226
本文介绍了在SwiftUI中将图像裁剪为正方形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将多个单元格彼此相邻放置,其中每个单元格由下面的图像和文本组成.单元格本身应为正方形,并且图像应缩放以填充剩余的空间(剪切图像的一部分).

I am trying to put multiple cells next to each other where each cell consists of an image and a text below. The cell itself should be a square and the image should be scaled to fill the remaining space (cutting a part of the image).

首先,我尝试仅使图像和下面的文本为正方形.现在我的问题是,我不知道如何在SwiftUI中正确实现这一目标.使用以下代码时,我可以使其正常工作:

First I tried just making the image square and the text below. Now my problem is, that I don't know how to properly achieve that in SwiftUI. I can get it to work, when using this code:

VStack {
    Image(uiImage: recipe.image!)
        .resizable()
        .aspectRatio(contentMode: .fill)
        .frame(width: 200, height: 200, alignment: .center)
        .clipped()
    Text(recipe.name)
}

问题是,我必须指定一个固定的帧大小.我想要的是一种制作单元格的方法,该单元格的纵横比保持1:1,并且可调整大小,因此我可以将它们的动态量放置在彼此相邻的屏幕上.

The problem is, that I have to specify a fixed frame size. What I want is a way to make a cell, that keeps an aspect ratio of 1:1 and is resizable, so I can fit a dynamic amount of them on a screen next to each other.

我也尝试使用

VStack {
    Image(uiImage: recipe.image!)
        .resizable()
        .aspectRatio(1.0, contentMode: .fit)
        .clipped()
    Text(recipe.name)
}

这给了我方形图像,可以动态缩放.但是问题在于,图像现在被拉伸以填充正方形,而无法缩放以填充它.

which gives me square images, that scale dynamically. But the problem is, that the image now gets stretched to fill the square and not scaled to fill it.

我的下一个想法是将其裁剪为正方形.为此,我首先尝试将其裁剪为圆形(因为显然没有正方形):

My next idea was to clip it to a square shape. For that I first tried to clip it into a circle shape (because apparently there is not square shape):

VStack {
    Image(uiImage: recipe.image!)
        .resizable()
        .aspectRatio(contentMode: .fit)
        .clipShape(Circle())
    Text(recipe.name)
}

但是出于某种奇怪的原因,它并没有真正裁剪图像,而是保留了剩余的空间...

But for some odd reason, it didn't really clip the image but instead kept the remaining space...

所以我看不到东西吗?还是将图像正方形裁剪为框架修改器的唯一选择?

So am I not seeing something or is the only option to clip an image square the frame modifier?

为了澄清:我不太关心文本,也不关心整个单元格(或者图像是否更简单)为正方形,而不必通过 .frame 和不会拉伸非方形原始图像以使其合适.

To clarify: I don't care about the text as much, as about the whole cell (or if it's simpler the image) being square, without having to specify its size via .frame and without the non-square original image being stretched to make it fit.

因此,理想的解决方案是VStack是方形的,但获得方形图像也可以.它应该看起来像图像1,但不必使用 .frame 修饰符.

So the perfect solution would be that the VStack is square but getting a square image would also be okay. It should look like Image 1, but without having to use the .frame modifier.

推荐答案

ZStack通过允许我们在不影响另一个布局的情况下对视图进行分层来帮助解决此问题.

A ZStack will help solve this by allowing us to layer views without one effecting the layout of the other.

对于文本:

.frame(minWidth:0,maxWidth:.infinity)将文本水平扩展到其父级的大小

.frame(minWidth: 0, maxWidth: .infinity) to expand the text horizontally to its parent's size

.frame(minHeight:0,maxHeight:.infinity)在其他情况下很有用

关于图片:

.aspectRatio(contentMode:.fill)可使图像保持其长宽比,而不是缩小到其帧的大小.

.aspectRatio(contentMode: .fill) to make the image maintain its aspect ratio rather than squashing to the size of its frame.

.layoutPriority(-1)取消对图像布局的优先级,以防止图像扩展其父对象( ForEach ZStack >在我们的情况下).

.layoutPriority(-1) to de-prioritize laying out the image to prevent it from expanding its parent (the ZStack within the ForEach in our case).

layoutPriority 的值仅需要低于父视图,该父视图默认情况下将设置为0.之所以必须这样做,是因为SwiftUI会在子级父级之前布置子级,并且除非我们手动设置不同的优先级,否则父级必须处理子级的大小.

The value for layoutPriority just needs to be lower than the parent views which will be set to 0 by default. We have to do this because SwiftUI will layout a child before its parent, and the parent has to deal with the child size unless we manually prioritize differently.

.clipped() 修改器使用边界框遮罩视图,因此您需要将其设置为裁剪任何尚未具有1:1纵横比的图像.

The .clipped() modifier uses the bounding frame to mask the view so you'll need to set it to clip any images that aren't already 1:1 aspect ratio.

    var body: some View {
        HStack {
            ForEach(0..<3, id: \.self) { index in
                ZStack {
                    Image(systemName: "doc.plaintext")
                        .resizable()
                        .aspectRatio(contentMode: .fill)
                        .layoutPriority(-1)
                    VStack {
                        Spacer()
                        Text("yes")
                            .frame(minWidth: 0, maxWidth: .infinity)
                            .background(Color.white)
                    }
                }
                .clipped()
                .aspectRatio(1, contentMode: .fit)
                .border(Color.red)
            }
        }
    }

虽然几何读取器非常有用,但我认为应尽可能避免使用它们.让SwiftUI完成工作会更干净.这是我使用 Geometry Reader 的最初解决方案效果也一样.

While geometry readers are super useful I think they should be avoided whenever possible. It's cleaner to let SwiftUI do the work. This is my initial solution with a Geometry Reader that works just as well.

        HStack {
            ForEach(0..<3, id: \.self) { index in
                ZStack {
                    GeometryReader { proxy in
                        Image(systemName: "pencil")
                            .resizable()
                            .scaledToFill()
                            .frame(width: proxy.size.width)
                        VStack {
                            Spacer()
                            Text("yes")
                                .frame(width: proxy.size.width)
                                .background(Color.white)
                        }
                    }
                }
                .clipped()
                .aspectRatio(1, contentMode: .fit)
                .border(Color.red)
            }
        }

这篇关于在SwiftUI中将图像裁剪为正方形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆