我正在尝试将多个单元格彼此相邻放置,其中每个单元格由下面的图像和文本组成。单元格本身应为正方形,并且图像应缩放以填充剩余的空间(剪切图像的一部分)。
首先,我尝试使图像和下面的文本变为正方形。 现在我的问题是,我不知道如何在SwiftUI中正确实现这一目标。使用以下代码时,我可以使其正常工作:
VStack {
Image(uiImage: recipe.image!)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 200, height: 200, alignment: .center)
.clipped()
Text(recipe.name)
}
问题是,我必须指定固定的帧大小。我想要的是一种制作单元格的方法,该单元格的纵横比保持1:1,并且可调整大小,因此我可以将它们的动态量放置在彼此相邻的屏幕上。
我也尝试使用
VStack {
Image(uiImage: recipe.image!)
.resizable()
.aspectRatio(1.0, contentMode: .fit)
.clipped()
Text(recipe.name)
}
这给了我方形图像,可以动态缩放。但是问题在于,图像现在被拉伸以填充正方形,而无法缩放以填充它。
我的下一个想法是将其裁剪为正方形。为此,我首先尝试将其裁剪为圆形(因为显然没有正方形):
VStack {
Image(uiImage: recipe.image!)
.resizable()
.aspectRatio(contentMode: .fit)
.clipShape(Circle())
Text(recipe.name)
}
但是出于某种奇怪的原因,它并没有真正裁剪图像,而是保留了剩余的空间...
所以我看不到东西吗?还是将图像正方形裁剪为框架修改器的唯一选择?
为了澄清:我不太在乎文本,也不在乎整个单元格(或者图像是否更简单)为正方形,而不必通过.frame
指定其大小,也不必方形原始图像被拉伸以使其适合。
因此,理想的解决方案是VStack是方形的,但是获得方形图像也可以。它应该看起来像图像1,但不必使用.frame
修饰符。
答案 0 :(得分:4)
我认为ZStack可能更适合您的需求,除非文本背后必须透明。在图片上尝试使用这些修饰符。
如果需要保持宽度动态,可以使用Geometry Reader
或初始化时传入的参数来研究。 .clipped()
modifier使用边界框遮罩视图,因此您需要将其设置为裁剪图像。
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)
}
}
答案 1 :(得分:2)
它对我有用,但我不知道为什么必须使用cornerRadius ...
import SwiftUI
struct ClippedImage: View {
let imageName: String
let width: CGFloat
let height: CGFloat
init(_ imageName: String, width: CGFloat, height: CGFloat) {
self.imageName = imageName
self.width = width
self.height = height
}
var body: some View {
ZStack {
Image(imageName)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: width, height: height)
}
.cornerRadius(0) // Necessary for working
.frame(width: width, height: height)
}
}
struct ClippedImage_Previews: PreviewProvider {
static var previews: some View {
ClippedImage("dishLarge1", width: 100, height: 100)
}
}