Grid Layout trong SwiftUI
1. LazyVGrid
Cơ bản
let columns = [
GridItem(.flexible()),
GridItem(.flexible())
]
LazyVGrid(columns: columns, spacing: 16) {
ForEach(0..<10) { index in
RoundedRectangle(cornerRadius: 8)
.fill(.blue)
.frame(height: 100)
.overlay(Text("\(index)").foregroundColor(.white))
}
}
.padding()GridItem Types
// Fixed width
GridItem(.fixed(100))
// Flexible (min đến max)
GridItem(.flexible(minimum: 80, maximum: 150))
// Adaptive (tự động fit nhiều items)
GridItem(.adaptive(minimum: 100))2. Grid Examples
2 Columns Fixed
let columns = [
GridItem(.fixed(150)),
GridItem(.fixed(150))
]3 Columns Flexible
let columns = Array(repeating: GridItem(.flexible()), count: 3)Adaptive (Auto-fit)
let columns = [
GridItem(.adaptive(minimum: 100, maximum: 150))
]3. LazyHGrid
let rows = [
GridItem(.fixed(60)),
GridItem(.fixed(60))
]
ScrollView(.horizontal) {
LazyHGrid(rows: rows, spacing: 12) {
ForEach(0..<20) { index in
RoundedRectangle(cornerRadius: 8)
.fill(.orange)
.frame(width: 80)
.overlay(Text("\(index)").foregroundColor(.white))
}
}
.padding()
}4. Spacing và Alignment
let columns = [
GridItem(.flexible(), spacing: 8),
GridItem(.flexible())
]
LazyVGrid(
columns: columns,
alignment: .center,
spacing: 16 // Vertical spacing
) {
// Items
}5. Grid (iOS 16+)
Non-lazy grid cho layout nhỏ.
Grid {
GridRow {
Text("Row 1, Col 1")
Text("Row 1, Col 2")
Text("Row 1, Col 3")
}
GridRow {
Text("Row 2, Col 1")
Text("Row 2, Col 2")
Text("Row 2, Col 3")
}
}Grid với Alignment
Grid(alignment: .leading, horizontalSpacing: 12, verticalSpacing: 8) {
GridRow {
Text("Name:")
Text("John Doe")
.gridColumnAlignment(.trailing)
}
GridRow {
Text("Email:")
Text("john@example.com")
}
}Spanning Columns
Grid {
GridRow {
Text("Header")
.gridCellColumns(2) // Span 2 columns
}
GridRow {
Text("Left")
Text("Right")
}
}6. Photo Grid
struct PhotoGrid: View {
let photos = Array(1...12)
let columns = [
GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible())
]
var body: some View {
ScrollView {
LazyVGrid(columns: columns, spacing: 2) {
ForEach(photos, id: \.self) { photo in
Rectangle()
.fill(.gray.opacity(0.3))
.aspectRatio(1, contentMode: .fill)
.overlay(
Image(systemName: "photo")
.foregroundColor(.gray)
)
}
}
}
}
}7. Product Grid
struct Product: Identifiable {
let id = UUID()
let name: String
let price: Double
}
struct ProductGrid: View {
let products: [Product]
let columns = [
GridItem(.adaptive(minimum: 160))
]
var body: some View {
ScrollView {
LazyVGrid(columns: columns, spacing: 16) {
ForEach(products) { product in
VStack(alignment: .leading) {
RoundedRectangle(cornerRadius: 8)
.fill(.gray.opacity(0.2))
.aspectRatio(1, contentMode: .fill)
Text(product.name)
.font(.headline)
Text("$\(product.price, specifier: "%.2f")")
.foregroundColor(.gray)
}
}
}
.padding()
}
}
}8. Calendar Grid
struct CalendarGrid: View {
let days = Array(1...31)
let columns = Array(repeating: GridItem(.flexible()), count: 7)
var body: some View {
VStack {
// Header
LazyVGrid(columns: columns) {
ForEach(["S", "M", "T", "W", "T", "F", "S"], id: \.self) { day in
Text(day)
.font(.caption)
.foregroundColor(.gray)
}
}
// Days
LazyVGrid(columns: columns, spacing: 8) {
ForEach(days, id: \.self) { day in
Text("\(day)")
.frame(width: 36, height: 36)
.background(
Circle()
.fill(day == 15 ? .blue : .clear)
)
.foregroundColor(day == 15 ? .white : .primary)
}
}
}
.padding()
}
}9. Section Headers
LazyVGrid(columns: columns, pinnedViews: [.sectionHeaders]) {
Section {
ForEach(0..<6) { _ in
RoundedRectangle(cornerRadius: 8)
.fill(.blue)
.frame(height: 100)
}
} header: {
Text("Section 1")
.font(.headline)
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
.background(.white)
}
Section {
ForEach(0..<6) { _ in
RoundedRectangle(cornerRadius: 8)
.fill(.green)
.frame(height: 100)
}
} header: {
Text("Section 2")
.font(.headline)
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
.background(.white)
}
}📝 Tóm tắt
| GridItem | Mô tả |
|---|---|
.fixed(size) | Kích thước cố định |
.flexible() | Co giãn trong khoảng |
.adaptive() | Tự động fit nhiều items |
| Component | Mục đích |
|---|---|
LazyVGrid | Grid dọc, lazy load |
LazyHGrid | Grid ngang, lazy load |
Grid | Non-lazy, iOS 16+ |
Last updated on