🔰adaptive column
SwiftUI ⟩ Layout ⟩ Grids ⟩ adaptive column
.adaptive(minimum:maximum):
a single GridItem may represent more than one column.
SwiftUI will try to fit as many minimum width columns as possible, but once the number of columns is determined, these can grow up to the maximum width provided, so it fills the full space.
The method to determine how much space will be given to this GridItem is the same used for the flexible case (without the clamping).
the minimum property of an adaptive column is only used to compute the number of items inside that column, it's NOT the minimum width of that column❗️👉 objc
本範例雖然只有指定兩個 GridItem:
let columns = [
GridItem(.fixed(70)), // ⭐ fixed column
GridItem(.adaptive(minimum: 40)) // ⭐ adaptive column
]但結果卻出現三個欄位,這主要是因為其中一個是 adaptive column,這種欄位可以一次容納多個項目 (cells)。

⬆️ 需要: 👔 ScrollVGridForEach
// ------------------------
// ⭐ 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)"))
}
}雖然本範例的 adaptive columen 有 minimum 屬性為 70:
let columns = [
GridItem(.flexible(minimum: 140)), // ⭐ flexible
GridItem(.adaptive(minimum: 70)) // ⭐ adaptive
]但此屬性並非 adaptive column 的最小寬度,而是用於計算能容納多少項目 (cells) 時使用。

struct ContentView: View {
let columns = [
GridItem(.flexible(minimum: 140)), // ⭐ flexible
GridItem(.adaptive(minimum: 70)) // ⭐ adaptive
]
var body: some View {
grid(columns)
}
}// r: remaining width
r = 200 // grid width
n = 2 // # of remaining cols
// r -= (fixed widths) + (spacing between cols)
r -= 8 // 192
// 1st col width
w1 = clamp(r/n) // 192/2 = 96
= 140 // clamped to [140, .inf)
// update r, n
r -= w1 // 192 - 140 = 52
n -= 1 // 1
// 2nd col width
w2 = clamp(r/n) // 52/1 = 52
= 52 // adaptive col is NOT clamped ⭐SwiftUI ⟩ Layout ⟩ LazyVGrid ⟩ .init(columns:alignment: ...)
Last updated
Was this helpful?