如何将图像剪辑到惰性网格内的正方形? (斯威夫特用户界面)
Posted
技术标签:
【中文标题】如何将图像剪辑到惰性网格内的正方形? (斯威夫特用户界面)【英文标题】:How do you clip an image to a square inside a lazy grid? (SwiftUI) 【发布时间】:2020-07-08 09:40:30 【问题描述】:这不是 this question 的副本。
您将在下面看到一个包含 3 列的矩形网格。我正在尝试使用图像来达到相同的效果。图像应被剪裁,否则不会显得拉伸或扭曲。
这是我实现矩形网格的方法...
// In my view struct...
private let threeColumnGrid = [
GridItem(.flexible(minimum: 40)),
GridItem(.flexible(minimum: 40)),
GridItem(.flexible(minimum: 40)),
]
// In my body...
LazyVGrid(columns: threeColumnGrid, alignment: .center)
ForEach(model.imageNames, id: \.self) imageName in
Rectangle()
.foregroundColor(.red)
.aspectRatio(1, contentMode: .fit)
这是我想要使用矩形的布局...
这是我的目标……
更新:
如果我这样做......
Image(item)
.resizable()
.aspectRatio(1, contentMode: .fit)
如果图像的纵横比不是 1:1,则图像会失真。例如,下面屏幕截图中的圆形图像应该是一个完美的圆形。
【问题讨论】:
图像有自己的尺寸,但形状(在本例中为矩形)没有,因此布局可能不同(输入参数相同)。你会以某种方式展示你期望从图像中得到什么吗? 我已经用我想要的示例更新了我的问题。 【参考方案1】:我找到了解决办法。
定义列数...
// Somewhere in my view struct
private let threeColumnGrid = [
GridItem(.flexible(minimum: 40)),
GridItem(.flexible(minimum: 40)),
GridItem(.flexible(minimum: 40)),
]
创建网格...
LazyVGrid(columns: threeColumnGrid, alignment: .center)
ForEach(model.imageNames, id: \.self) item in
GeometryReader gr in
Image(item)
.resizable()
.scaledToFill()
.frame(height: gr.size.width)
.clipped()
.aspectRatio(1, contentMode: .fit)
【讨论】:
这为我解决了同样的问题,但将框架修饰符更改为 .frame(height: gr.size.width) 以便我的图像始终具有相同的宽度和高度。我很好奇在这里将框架的宽度设置为几何体的建议宽度有什么作用。 是我还是这不是图像在正方形中间的中心? 试试这个框架修饰符:frame(height: gr.size.width, alignment: .center)【参考方案2】:我发现 DPMitu 的答案没有使图像居中(它与前缘对齐)。
这对我来说效果更好(也不需要 GeometryReader):
LazyVGrid(columns: columns, spacing: 30)
ForEach(items) item in
Image("IMG_0044")
.resizable()
.scaledToFill()
.frame(minWidth: 0, maxWidth: .infinity)
.aspectRatio(1, contentMode: .fill)
.clipped() //Alternatively you can use cornerRadius for the same effect
//.cornerRadius(10)
我在这里找到它https://www.appcoda.com/learnswiftui/swiftui-gridlayout.html 大约在页面的一半
【讨论】:
这似乎无法实现肖像图像的方形效果... 要实现与肖像图像相同的效果,请将 .frame() 行更改为 .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)。只要父视图的框架是方形的,它就应该以这种方式与横向和纵向一起使用。 拯救了我的一天,谢谢【参考方案3】:有些人询问图像是否偏离中心。您可以通过添加.position(x: gr.frame(in: .local).midX, y: gr.frame(in: .local).midY)
来调整它。所以完整的事情是:
列数
// Somewhere in my view struct
private let threeColumnGrid = [
GridItem(.flexible(minimum: 40)),
GridItem(.flexible(minimum: 40)),
GridItem(.flexible(minimum: 40)),
]
创建网格
LazyVGrid(columns: threeColumnGrid, alignment: .center)
ForEach(model.imageNames, id: \.self) item in
GeometryReader gr in
Image(item)
.resizable()
.scaledToFill()
.frame(height: gr.size.width)
.position(x: gr.frame(in: .local).midX, y: gr.frame(in: .local).midY)
.clipped()
.aspectRatio(1, contentMode: .fit)
【讨论】:
【参考方案4】:没有GeometryReader
的解决方案和正确缩放的图像。
struct ContentView: View
private let columns = [
GridItem(.flexible(minimum: 40)),
GridItem(.flexible(minimum: 40)),
GridItem(.flexible(minimum: 40)),
]
private let imageNames = ["image0", "image1", "image2", "image3", "image4"];
var body: some View
LazyVGrid(columns: columns, content:
ForEach(imageNames, id: \.self) name in
Color.clear
.background(Image(name)
.resizable()
.scaledToFill()
)
.aspectRatio(1, contentMode: .fill)
.clipped()
.contentShape(Rectangle()) // <-- this is important to fix gesture recognition
)
【讨论】:
【参考方案5】:我用一些随机图像复制了一些代码并得到了以下内容。但不确定您的目标,但希望对您有所帮助
使用 Xcode 12 / ios 14 测试
struct TestImagesInGrid: View
@State private var imageNames: [String]
private let threeColumnGrid = [
GridItem(.flexible(minimum: 40)),
GridItem(.flexible(minimum: 40)),
GridItem(.flexible(minimum: 40)),
]
init()
_imageNames = State(initialValue: (0..<8).map _ in
"image_\(Int.random(in: 1...3))"
)
var body: some View
LazyVGrid(columns: threeColumnGrid, alignment: .center)
ForEach(imageNames.indices) i in
Image(imageNames[i]).resizable()
.aspectRatio(1, contentMode: .fit)
【讨论】:
我已经使用您的技术更新了我的问题。这仅适用于图像的纵横比已经为 1:1 的情况。【参考方案6】:我遇到了类似的问题,我就是这样解决的。
GeometryReader geo in
Image(item)
.resizable()
.aspectRatio(contentMode: .fill)
.clipShape(
Rectangle()
.size(width: geo.size.width, height: geo.size.width)
)
【讨论】:
【参考方案7】:我使用 Rectangle 来实现帮助,就在下面
LazyVGrid(columns: [.init(.adaptive(minimum: 88, maximum: 128), spacing: 2)], spacing: 2)
ForEach(urls, id: \.self) url in
Rectangle()
.aspectRatio(1, contentMode: .fit)
.foregroundColor(.clear)
.overlay
GeometryReader geometry in
if let image = UIImage(contentsOfFile: url.relativePath)
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: geometry.size.width, height: geometry.size.height, alignment: .center)
.clipped()
【讨论】:
以上是关于如何将图像剪辑到惰性网格内的正方形? (斯威夫特用户界面)的主要内容,如果未能解决你的问题,请参考以下文章