๐ฐ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)
}
}
ๆฌไฝๅฏฌๅบฆ็่จ็ฎๆนๅผ๏ผ๐ grid layout algorithm
// 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