SwiftUI的LazyVGrid动态行高

8
我希望能够创建一行高度相同的LazyVGrid,使其扩展/收缩以填充可用的父高度。
这个可能吗?
let columns = Array(repeating: GridItem(.flexible(minimum: 50, maximum: 100)), count: 3)
LazyVGrid(columns: columns, alignment: .leading, spacing: 10) {
  ForEach(objects, id: \.self.id) { object in
    MyView().frame(minHeight: 0, maxHeight: .infinity)
  }
}

上述代码完美地调整了帧的宽度间距,但行不会扩展和收缩,它们只会紧贴内容的高度。

期望效果


你解决了吗?我对LazyVGrid的动态行高度很感兴趣。 - Aecasorg
没有找到合适的动态解决方案。我通过将固定高度硬编码到整个LazyVGrid中来解决了我的问题。我最初希望它能够扩展到父窗口的大小(正在开发一个OS X应用程序)。 - Simon Borkin
1个回答

6
这里有一个占用所有可用高度的网格示例。虽然有更通用的实现方式,但希望您能清楚地了解如何实现。
struct ContentView: View {
    let numOfItems = 10
    let numOfColumns = 3
    let spacing: CGFloat = 10
    
    var body: some View {
        GeometryReader { g in
            let columns = Array(repeating: GridItem(.flexible(minimum: 50, maximum: 100)), count: numOfColumns)
            let numOfRows: Int = Int(ceil(Double(numOfItems) / Double(numOfColumns)))
            let height: CGFloat = (g.size.height - (spacing * CGFloat(numOfRows - 1))) / CGFloat(numOfRows)

            LazyVGrid(columns: columns, alignment: .leading, spacing: spacing) {
                ForEach(0..<numOfItems, id: \.self) { object in
                    MyView().frame(minHeight: height, maxHeight: .infinity)
                }
            }
        }
    }}

struct MyView: View {
    var body: some View {
        Color(red: Double.random(in: 0...1), green: Double.random(in: 0...1), blue: Double.random(in: 0...1))
    }
}

下面是一个可重复使用的网格版本:

struct ContentView: View {
    let colors = [UIColor.red, .black, .blue, .brown, .gray, .green, .cyan, .magenta, .orange, .purple]
    var body: some View {
        TallVGrid(items: colors, idKeyPath: \.self, numOfColumns: 4, vSpacing: 20, content: { color in
            ColorView(uiColor: color)
            Text("Some \(Int.random(in: 0...10))")
        })
    }
}

struct TallVGrid<Item, ItemView, I>: View where ItemView: View, I: Hashable {
    var items: [Item]
    var idKeyPath: KeyPath<Item, I>
    var numOfItems : Int {
        items.count
    }
    var numOfColumns : Int = 3
    var vSpacing: CGFloat = 10
    @ViewBuilder var content: (Item) -> ItemView
    
    var body: some View {
        GeometryReader { g in
            let columns = Array(repeating: GridItem(.flexible(minimum: 50, maximum: 100)), count: numOfColumns)
            let numOfRows: Int = Int(ceil(Double(numOfItems) / Double(numOfColumns)))
            let height: CGFloat = (g.size.height - (vSpacing * CGFloat(numOfRows - 1))) / CGFloat(numOfRows)
            
            LazyVGrid(columns: columns, alignment: .leading, spacing: vSpacing) {
                ForEach(items, id: idKeyPath) { item in
                    VStack {
                        content(item)
                    }
                    .frame(minHeight: height, maxHeight: .infinity)
                }
            }
        }
    }
}


struct ColorView: View {
    let uiColor: UIColor
    var body: some View {
        Color(uiColor)
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接