这是一个采用所有可用高度的网格示例。可以用更通用的方式来做,但我希望如何做的想法很清楚。
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)
}
}