72 lines
1.8 KiB
Markdown
72 lines
1.8 KiB
Markdown
# Grids
|
||
|
||
## Intent
|
||
|
||
Use `LazyVGrid` for icon pickers, media galleries, and dense visual selections where items align in columns.
|
||
|
||
## Core patterns
|
||
|
||
- Use `.adaptive` columns for layouts that should scale across device sizes.
|
||
- Use multiple `.flexible` columns when you want a fixed column count.
|
||
- Keep spacing consistent and small to avoid uneven gutters.
|
||
- Use `GeometryReader` inside grid cells when you need square thumbnails.
|
||
|
||
## Example: adaptive icon grid
|
||
|
||
```swift
|
||
let columns = [GridItem(.adaptive(minimum: 120, maximum: 1024))]
|
||
|
||
LazyVGrid(columns: columns, spacing: 6) {
|
||
ForEach(icons) { icon in
|
||
Button {
|
||
select(icon)
|
||
} label: {
|
||
ZStack(alignment: .bottomTrailing) {
|
||
Image(icon.previewName)
|
||
.resizable()
|
||
.aspectRatio(contentMode: .fit)
|
||
.cornerRadius(6)
|
||
if icon.isSelected {
|
||
Image(systemName: "checkmark.seal.fill")
|
||
.padding(4)
|
||
.tint(.green)
|
||
}
|
||
}
|
||
}
|
||
.buttonStyle(.plain)
|
||
}
|
||
}
|
||
```
|
||
|
||
## Example: fixed 3-column media grid
|
||
|
||
```swift
|
||
LazyVGrid(
|
||
columns: [
|
||
.init(.flexible(minimum: 100), spacing: 4),
|
||
.init(.flexible(minimum: 100), spacing: 4),
|
||
.init(.flexible(minimum: 100), spacing: 4),
|
||
],
|
||
spacing: 4
|
||
) {
|
||
ForEach(items) { item in
|
||
GeometryReader { proxy in
|
||
ThumbnailView(item: item)
|
||
.frame(width: proxy.size.width, height: proxy.size.width)
|
||
}
|
||
.aspectRatio(1, contentMode: .fit)
|
||
}
|
||
}
|
||
```
|
||
|
||
## Design choices to keep
|
||
|
||
- Use `LazyVGrid` for large collections; avoid non-lazy grids for big sets.
|
||
- Keep tap targets full-bleed using `.contentShape(Rectangle())` when needed.
|
||
- Prefer adaptive grids for settings pickers and flexible layouts.
|
||
|
||
## Pitfalls
|
||
|
||
- Avoid heavy overlays in every grid cell; it can be expensive.
|
||
- Don’t nest grids inside other grids without a clear reason.
|