本範例雖然只有指定兩個 GridItem :
Copy let columns = [
GridItem ( .fixed ( 70 )) , // ⭐ fixed column
GridItem ( .adaptive ( minimum : 40 )) // ⭐ adaptive column
]
但結果卻出現三個欄位 ,這主要是因為其中一個是 adaptive column ,這種欄位可以一次容納多個項目 (cells )。
Copy // ------------------------
// ⭐ Fixed Column
// ------------------------
//
// always rendered at the specified width
// (no matter how much space is available)
// ---------------------------
// ⭐ Adaptive Column
// ---------------------------
//
// ⭐ tries to accommodate "as many items as possible"
// ⭐ the "minimum" property of an "adaptive column" is only used
// to compute how many items that column can accommodate,
// it's NOT the minimum width of that column❗️
// (adaptive column's width could be SMALLER than this property)
// ⭐ 1. (remaining width)
// = (grid width) - (fixed widths) - (spaces between 2 columns)
// = (200) - (70) - (8 * 1)
// = (122)
//
// ⭐ 2. calculate (how many items) an adaptive column can accommodate:
// (remaining width) - (first item) - (following items) > 0
// given:
// minimum width = (40), spacing = (8) : ⭐ default
// fist item = (40), following item = (8 + 40)
//
// (122) - (40) - (48) * 1 = 34 > 0 ... ✅ (accommodate 2 items)
// (122) - (40) - (48) * 2 = -14 < 0 ... ❌
//
// ⭐ 3. (item width)
// = [(remaining) - (spaces between 2 items)] / (2 items)
// = [(122) - (8 * 1)] / 2
// = 114 / 2
// = 57 ............ (proposed size for each item) ⭐
//
// ⭐ result:
//
// ╭──fixed──╮ ╭───── adaptive ──────╮ (one adaptive column)
// [ 70 ][8][ 57 ][8][ 57 ]
// ╰──item──╯ ╰──item──╯ (two grid items)
struct ContentView: View {
let columns = [
GridItem(.fixed(70)), // ⭐ fixed column
GridItem(.adaptive(minimum: 40)) // ⭐ adaptive column
]
var body: some View {
grid(columns)
}
}
extension ContentView {
/// a grid of swatches
func grid(_ columns: [GridItem]) -> some View {
// 👔 ScrollVGridForEach
ScrollVGridForEach(0..<100, columns: columns){
numberSwatch($0)
}
.frame(width: 200) // grid width = scroll view width ⭐
.border(Color.yellow) // scroll view border (yellow)
.padding()
.border(Color.blue) // padding border (blue)
.frame(height: 300)
}
/// a color swatch with a number on it
@ViewBuilder func numberSwatch(_ i: Int) -> some View {
let color: Color = i % 3 == 0 ? .green : .pink
color
.opacity(0.3)
.frame(height: 40)
.overlay(Text("\(i)"))
}
}