【问题标题】: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,则图像会失真。例如,下面屏幕截图中的圆形图像应该是一个完美的圆形。

【问题讨论】:

  • 图像有自己的尺寸,但形状(在本例中为矩形)没有,因此布局可能不同(输入参数相同)。你会以某种方式展示你期望从图像中得到什么吗?
  • 我已经用我想要的示例更新了我的问题。

标签: ios swiftui


【解决方案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()
                            }
                        }
                    }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2023-03-14
          • 1970-01-01
          • 2017-07-22
          • 2017-03-24
          • 2018-09-01
          • 2020-03-26
          • 2021-11-21
          • 1970-01-01
          • 2020-10-02
          相关资源
          最近更新 更多