【问题标题】:Constraint-based layout of images in a list in SwiftUISwiftUI 列表中基于约束的图像布局
【发布时间】:2021-06-03 16:32:24
【问题描述】:

我想在SwiftUI List 中实现以下基于约束的图像布局:

  • 将每个Image 的左/右边缘固定到列表边距(适应屏幕大小)
  • 基于纵横比的动态高度(我也可以使用固定高度)
  • 保持图片纵横比,内容应填满空间

我尝试过但不起作用的方法(基于this article):

struct MyView: View {
  @ObservedObject var viewModel: MyViewModel
  let aspectRatio = CGSize(width: 345, height: 120)

  var body: some View {
    List {
      ForEach(viewModel.items) { item in
        GeometryReader { geo in
          Image("test_image")
            .resizable()
            .aspectRatio(aspectRatio, contentMode: .fill)
            .frame(width: geo.size.width)
            .clipped()
        }
      }
    }
  }
}

我从geo 得到的尺寸在 iPhone 11 Pro 上是 (343, 32)。宽度是有道理的,但由于某种原因,它不会让单元格扩展超过 32 的高度。欢迎任何提示,因为我真的开始怀念自动布局约束了。

【问题讨论】:

    标签: ios swift image layout swiftui


    【解决方案1】:

    不需要使用GeometryReader 来处理这样的事情。对于固定高度,您只能提供 frameheight。您也不需要创建自己的 let aspectRatio = CGSize(width: 345, height: 120) - 如果您将其保留为 nil(默认情况下)应该没问题。

    编辑:使用 padding 而不是 VStack 带间距

    struct MyView: View {
        var body: some View {
            List {
                ForEach(0..<10, id: \.self) { item in
                    Image("test_image")
                        .resizable()
                        .aspectRatio(contentMode: .fill) /// no need for custom aspect ratio
                        .frame(height: 120) /// fixed height of image
                        .clipped() /// stop image from overflowing
                        .padding(.vertical, 12) /// extra vertical padding
                }
            }
        }
    }
    

    结果("test_image"):


    但是,它的高度固定为120,因此图像的顶部和底部都被裁剪掉了。要解决此问题,您可以完全避免使用 frameclipped

    struct MyView: View {
        var body: some View {
            List {
                ForEach(0..<10, id: \.self) { item in
                    Image("test_image")
                        .resizable()
                        .aspectRatio(contentMode: .fill) /// doesn't matter if it's fit or fill
                        .padding(.vertical, 12) /// extra vertical padding
                }
            }
        }
    }
    

    结果:

    【讨论】:

    • 为什么会有VStack List?不应该是要么吗?不过谢谢你,这让我走上了正轨。不回答动态高度问题,但在这一点上这将是一个奖励。
    • @rmp251 你是对的,它应该是ListVStack + ScrollView。我只为间距做了 VStack - 我会更新我的答案。
    • 当图像相对于固定高度非常宽时,此解决方案似乎会中断。它不允许宽度受边距限制。但是它适用于“高”图像(例如正方形)。
    猜你喜欢
    • 1970-01-01
    • 2017-11-05
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-12
    • 2019-11-24
    • 2019-09-19
    相关资源
    最近更新 更多