Bỏ qua để đến nội dung

Grid Layout

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()
// 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))
let columns = [
GridItem(.fixed(150)),
GridItem(.fixed(150))
]
let columns = Array(repeating: GridItem(.flexible()), count: 3)
let columns = [
GridItem(.adaptive(minimum: 100, maximum: 150))
]
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()
}
let columns = [
GridItem(.flexible(), spacing: 8),
GridItem(.flexible())
]
LazyVGrid(
columns: columns,
alignment: .center,
spacing: 16 // Vertical spacing
) {
// Items
}

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(alignment: .leading, horizontalSpacing: 12, verticalSpacing: 8) {
GridRow {
Text("Name:")
Text("John Doe")
.gridColumnAlignment(.trailing)
}
GridRow {
Text("Email:")
Text("john@example.com")
}
}
Grid {
GridRow {
Text("Header")
.gridCellColumns(2) // Span 2 columns
}
GridRow {
Text("Left")
Text("Right")
}
}
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)
)
}
}
}
}
}
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()
}
}
}
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()
}
}
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)
}
}

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+