axiom-swiftui-containers-ref

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

SwiftUI Containers Reference

SwiftUI 容器参考文档

Stacks, grids, outlines, and scroll enhancements. iOS 14 through iOS 26.
Sources: WWDC 2020-10031, 2022-10056, 2023-10148, 2024-10144, 2025-256
栈、网格、大纲及滚动增强功能。覆盖iOS 14至iOS 26版本。
资料来源:WWDC 2020-10031、2022-10056、2023-10148、2024-10144、2025-256

Quick Decision

快速决策指南

Use CaseContaineriOS
Fixed views vertical/horizontalVStack / HStack13+
Overlapping viewsZStack13+
Large scrollable listLazyVStack / LazyHStack14+
Multi-column gridLazyVGrid14+
Multi-row grid (horizontal)LazyHGrid14+
Static grid, precise alignmentGrid16+
Hierarchical data (tree)List with
children:
14+
Custom hierarchiesOutlineGroup14+
Show/hide contentDisclosureGroup14+

使用场景容器组件iOS版本
固定垂直/水平视图VStack / HStack13+
重叠视图ZStack13+
大型可滚动列表LazyVStack / LazyHStack14+
多列网格LazyVGrid14+
多行水平网格LazyHGrid14+
静态网格、精确对齐Grid16+
层级数据(树形结构)
children:
参数的List
14+
自定义层级结构OutlineGroup14+
显示/隐藏内容DisclosureGroup14+

Part 1: Stacks

第一部分:栈组件

VStack, HStack, ZStack

VStack, HStack, ZStack

swift
VStack(alignment: .leading, spacing: 12) {
    Text("Title")
    Text("Subtitle")
}

HStack(alignment: .top, spacing: 8) {
    Image(systemName: "star")
    Text("Rating")
}

ZStack(alignment: .bottomTrailing) {
    Image("photo")
    Badge()
}
ZStack alignments:
.center
(default),
.top
,
.bottom
,
.leading
,
.trailing
,
.topLeading
,
.topTrailing
,
.bottomLeading
,
.bottomTrailing
swift
VStack(alignment: .leading, spacing: 12) {
    Text("Title")
    Text("Subtitle")
}

HStack(alignment: .top, spacing: 8) {
    Image(systemName: "star")
    Text("Rating")
}

ZStack(alignment: .bottomTrailing) {
    Image("photo")
    Badge()
}
ZStack 对齐方式
.center
(默认)、
.top
.bottom
.leading
.trailing
.topLeading
.topTrailing
.bottomLeading
.bottomTrailing

Spacer

Spacer

swift
HStack {
    Text("Left")
    Spacer()
    Text("Right")
}

Spacer(minLength: 20)  // Minimum size

swift
HStack {
    Text("Left")
    Spacer()
    Text("Right")
}

Spacer(minLength: 20)  // 最小尺寸

LazyVStack, LazyHStack (iOS 14+)

LazyVStack, LazyHStack (iOS 14+)

Render children only when visible. Use inside ScrollView.
swift
ScrollView {
    LazyVStack(spacing: 0) {
        ForEach(items) { item in
            ItemRow(item: item)
        }
    }
}
仅在视图可见时渲染子组件。需在ScrollView内使用。
swift
ScrollView {
    LazyVStack(spacing: 0) {
        ForEach(items) { item in
            ItemRow(item: item)
        }
    }
}

Pinned Section Headers

固定分区头部

swift
ScrollView {
    LazyVStack(pinnedViews: [.sectionHeaders]) {
        ForEach(sections) { section in
            Section(header: SectionHeader(section)) {
                ForEach(section.items) { item in
                    ItemRow(item: item)
                }
            }
        }
    }
}

swift
ScrollView {
    LazyVStack(pinnedViews: [.sectionHeaders]) {
        ForEach(sections) { section in
            Section(header: SectionHeader(section)) {
                ForEach(section.items) { item in
                    ItemRow(item: item)
                }
            }
        }
    }
}

Part 2: Grids

第二部分:网格组件

Grid (iOS 16+)

Grid (iOS 16+)

Non-lazy grid with precise alignment. Loads all views at once.
swift
Grid(alignment: .leading, horizontalSpacing: 10, verticalSpacing: 10) {
    GridRow {
        Text("Name")
        TextField("Enter name", text: $name)
    }
    GridRow {
        Text("Email")
        TextField("Enter email", text: $email)
    }
}
Modifiers:
  • gridCellColumns(_:)
    — Span multiple columns
  • gridColumnAlignment(_:)
    — Override column alignment
swift
Grid {
    GridRow {
        Text("Header").gridCellColumns(2)
    }
    GridRow {
        Text("Left")
        Text("Right").gridColumnAlignment(.trailing)
    }
}

非懒加载网格,支持精确对齐。一次性加载所有视图。
swift
Grid(alignment: .leading, horizontalSpacing: 10, verticalSpacing: 10) {
    GridRow {
        Text("Name")
        TextField("Enter name", text: $name)
    }
    GridRow {
        Text("Email")
        TextField("Enter email", text: $email)
    }
}
修饰符
  • gridCellColumns(_:)
    — 跨多列
  • gridColumnAlignment(_:)
    — 覆盖列对齐方式
swift
Grid {
    GridRow {
        Text("Header").gridCellColumns(2)
    }
    GridRow {
        Text("Left")
        Text("Right").gridColumnAlignment(.trailing)
    }
}

LazyVGrid (iOS 14+)

LazyVGrid (iOS 14+)

Vertical-scrolling grid. Define columns; rows grow unbounded.
swift
let columns = [
    GridItem(.flexible()),
    GridItem(.flexible()),
    GridItem(.flexible())
]

ScrollView {
    LazyVGrid(columns: columns, spacing: 16) {
        ForEach(items) { item in
            ItemCard(item: item)
        }
    }
}
垂直滚动网格。定义;行数无限制扩展。
swift
let columns = [
    GridItem(.flexible()),
    GridItem(.flexible()),
    GridItem(.flexible())
]

ScrollView {
    LazyVGrid(columns: columns, spacing: 16) {
        ForEach(items) { item in
            ItemCard(item: item)
        }
    }
}

LazyHGrid (iOS 14+)

LazyHGrid (iOS 14+)

Horizontal-scrolling grid. Define rows; columns grow unbounded.
swift
let rows = [GridItem(.fixed(100)), GridItem(.fixed(100))]

ScrollView(.horizontal) {
    LazyHGrid(rows: rows, spacing: 16) {
        ForEach(items) { item in
            ItemCard(item: item)
        }
    }
}
水平滚动网格。定义;列数无限制扩展。
swift
let rows = [GridItem(.fixed(100)), GridItem(.fixed(100))]

ScrollView(.horizontal) {
    LazyHGrid(rows: rows, spacing: 16) {
        ForEach(items) { item in
            ItemCard(item: item)
        }
    }
}

GridItem.Size

GridItem.Size

SizeBehavior
.fixed(CGFloat)
Exact width/height
.flexible(minimum:maximum:)
Fills space equally
.adaptive(minimum:maximum:)
Creates as many as fit
swift
// Adaptive: responsive column count
let columns = [GridItem(.adaptive(minimum: 150))]

尺寸类型行为
.fixed(CGFloat)
精确宽度/高度
.flexible(minimum:maximum:)
均分可用空间
.adaptive(minimum:maximum:)
自动创建尽可能多的列/行
swift
// 自适应:响应式列数
let columns = [GridItem(.adaptive(minimum: 150))]

Part 3: Outlines

第三部分:大纲组件

List with Hierarchical Data (iOS 14+)

带层级数据的List (iOS 14+)

swift
struct FileItem: Identifiable {
    let id = UUID()
    var name: String
    var children: [FileItem]?  // nil = leaf
}

List(files, children: \.children) { file in
    Label(file.name, systemImage: file.children != nil ? "folder" : "doc")
}
.listStyle(.sidebar)
swift
struct FileItem: Identifiable {
    let id = UUID()
    var name: String
    var children: [FileItem]?  // nil = 叶子节点
}

List(files, children: \.children) { file in
    Label(file.name, systemImage: file.children != nil ? "folder" : "doc")
}
.listStyle(.sidebar)

OutlineGroup (iOS 14+)

OutlineGroup (iOS 14+)

For custom hierarchical layouts outside List.
swift
List {
    ForEach(canvases) { canvas in
        Section(header: Text(canvas.name)) {
            OutlineGroup(canvas.graphics, children: \.children) { graphic in
                GraphicRow(graphic: graphic)
            }
        }
    }
}
用于List之外的自定义层级布局。
swift
List {
    ForEach(canvases) { canvas in
        Section(header: Text(canvas.name)) {
            OutlineGroup(canvas.graphics, children: \.children) { graphic in
                GraphicRow(graphic: graphic)
            }
        }
    }
}

DisclosureGroup (iOS 14+)

DisclosureGroup (iOS 14+)

swift
@State private var isExpanded = false

DisclosureGroup("Advanced Options", isExpanded: $isExpanded) {
    Toggle("Enable Feature", isOn: $feature)
    Slider(value: $intensity)
}

swift
@State private var isExpanded = false

DisclosureGroup("高级选项", isExpanded: $isExpanded) {
    Toggle("启用功能", isOn: $feature)
    Slider(value: $intensity)
}

Part 4: Common Patterns

第四部分:常见模式

Photo Grid

照片网格

swift
let columns = [GridItem(.adaptive(minimum: 100), spacing: 2)]

ScrollView {
    LazyVGrid(columns: columns, spacing: 2) {
        ForEach(photos) { photo in
            AsyncImage(url: photo.thumbnailURL) { image in
                image.resizable().aspectRatio(1, contentMode: .fill)
            } placeholder: { Color.gray }
            .aspectRatio(1, contentMode: .fill)
            .clipped()
        }
    }
}
swift
let columns = [GridItem(.adaptive(minimum: 100), spacing: 2)]

ScrollView {
    LazyVGrid(columns: columns, spacing: 2) {
        ForEach(photos) { photo in
            AsyncImage(url: photo.thumbnailURL) { image in
                image.resizable().aspectRatio(1, contentMode: .fill)
            } placeholder: { Color.gray }
            .aspectRatio(1, contentMode: .fill)
            .clipped()
        }
    }
}

Horizontal Carousel

水平轮播

swift
ScrollView(.horizontal, showsIndicators: false) {
    LazyHStack(spacing: 16) {
        ForEach(items) { item in
            CarouselCard(item: item).frame(width: 280)
        }
    }
    .padding(.horizontal)
}
swift
ScrollView(.horizontal, showsIndicators: false) {
    LazyHStack(spacing: 16) {
        ForEach(items) { item in
            CarouselCard(item: item).frame(width: 280)
        }
    }
    .padding(.horizontal)
}

File Browser

文件浏览器

swift
List(selection: $selection) {
    OutlineGroup(rootItems, children: \.children) { item in
        Label {
            Text(item.name)
        } icon: {
            Image(systemName: item.children != nil ? "folder.fill" : "doc.fill")
        }
    }
}
.listStyle(.sidebar)

swift
List(selection: $selection) {
    OutlineGroup(rootItems, children: \.children) { item in
        Label {
            Text(item.name)
        } icon: {
            Image(systemName: item.children != nil ? "folder.fill" : "doc.fill")
        }
    }
}
.listStyle(.sidebar)

Part 5: Performance

第五部分:性能优化

When to Use Lazy

何时使用懒加载

SizeScrollable?Use
1-20NoVStack/HStack
1-20YesVStack/HStack in ScrollView
20-100YesLazyVStack/LazyHStack
100+YesLazyVStack/LazyHStack or List
Grid <50NoGrid
Grid 50+YesLazyVGrid/LazyHGrid
Cache GridItem arrays — define outside body:
swift
struct ContentView: View {
    let columns = [GridItem(.adaptive(minimum: 150))]  // ✅
    var body: some View {
        LazyVGrid(columns: columns) { ... }
    }
}
数量是否可滚动使用组件
1-20VStack/HStack
1-20ScrollView内的VStack/HStack
20-100LazyVStack/LazyHStack
100+LazyVStack/LazyHStack 或 List
网格 <50Grid
网格 50+LazyVGrid/LazyHGrid
缓存GridItem数组 — 在body外部定义:
swift
struct ContentView: View {
    let columns = [GridItem(.adaptive(minimum: 150))]  // ✅
    var body: some View {
        LazyVGrid(columns: columns) { ... }
    }
}

iOS 26 Performance

iOS 26 性能提升

  • 6x faster list loading for 100k+ items
  • 16x faster list updates
  • Reduced dropped frames in scrolling
  • Nested ScrollViews with lazy stacks now properly defer loading:
swift
ScrollView(.horizontal) {
    LazyHStack {
        ForEach(photoSets) { set in
            ScrollView(.vertical) {
                LazyVStack {
                    ForEach(set.photos) { PhotoView(photo: $0) }
                }
            }
        }
    }
}

  • 10万+项列表加载速度提升6倍
  • 列表更新速度提升16倍
  • 滚动时丢帧情况减少
  • 嵌套ScrollView与懒加载栈现在可正确延迟加载:
swift
ScrollView(.horizontal) {
    LazyHStack {
        ForEach(photoSets) { set in
            ScrollView(.vertical) {
                LazyVStack {
                    ForEach(set.photos) { PhotoView(photo: $0) }
                }
            }
        }
    }
}

Part 6: Scroll Enhancements

第六部分:滚动增强功能

containerRelativeFrame (iOS 17+)

containerRelativeFrame (iOS 17+)

Size views relative to scroll container.
swift
ScrollView(.horizontal) {
    LazyHStack {
        ForEach(cards) { card in
            CardView(card: card)
                .containerRelativeFrame(.horizontal, count: 3, span: 1, spacing: 16)
        }
    }
}
相对于滚动容器设置视图尺寸。
swift
ScrollView(.horizontal) {
    LazyHStack {
        ForEach(cards) { card in
            CardView(card: card)
                .containerRelativeFrame(.horizontal, count: 3, span: 1, spacing: 16)
        }
    }
}

scrollTargetLayout (iOS 17+)

scrollTargetLayout (iOS 17+)

Enable snapping.
swift
ScrollView(.horizontal) {
    LazyHStack {
        ForEach(items) { ItemCard(item: $0) }
    }
    .scrollTargetLayout()
}
.scrollTargetBehavior(.viewAligned)
启用吸附效果。
swift
ScrollView(.horizontal) {
    LazyHStack {
        ForEach(items) { ItemCard(item: $0) }
    }
    .scrollTargetLayout()
}
.scrollTargetBehavior(.viewAligned)

scrollPosition (iOS 17+)

scrollPosition (iOS 17+)

Track topmost visible item. Requires
.id()
on each item.
swift
@State private var position: Item.ID?

ScrollView {
    LazyVStack {
        ForEach(items) { item in
            ItemRow(item: item).id(item.id)
        }
    }
}
.scrollPosition(id: $position)
跟踪最顶部的可见项。要求每个项都有
.id()
swift
@State private var position: Item.ID?

ScrollView {
    LazyVStack {
        ForEach(items) { item in
            ItemRow(item: item).id(item.id)
        }
    }
}
.scrollPosition(id: $position)

scrollTransition (iOS 17+)

scrollTransition (iOS 17+)

swift
.scrollTransition { content, phase in
    content
        .opacity(1 - abs(phase.value) * 0.5)
        .scaleEffect(phase.isIdentity ? 1.0 : 0.75)
}
swift
.scrollTransition { content, phase in
    content
        .opacity(1 - abs(phase.value) * 0.5)
        .scaleEffect(phase.isIdentity ? 1.0 : 0.75)
}

onScrollGeometryChange (iOS 18+)

onScrollGeometryChange (iOS 18+)

swift
.onScrollGeometryChange(for: Bool.self) { geo in
    geo.contentOffset.y < geo.contentInsets.top
} action: { _, isTop in
    showBackButton = !isTop
}
swift
.onScrollGeometryChange(for: Bool.self) { geo in
    geo.contentOffset.y < geo.contentInsets.top
} action: { _, isTop in
    showBackButton = !isTop
}

onScrollVisibilityChange (iOS 18+)

onScrollVisibilityChange (iOS 18+)

swift
VideoPlayer(player: player)
    .onScrollVisibilityChange(threshold: 0.2) { visible in
        visible ? player.play() : player.pause()
    }

swift
VideoPlayer(player: player)
    .onScrollVisibilityChange(threshold: 0.2) { visible in
        visible ? player.play() : player.pause()
    }

Resources

资源

WWDC: 2020-10031, 2022-10056, 2023-10148, 2024-10144, 2025-256
Docs: /swiftui/lazyvstack, /swiftui/lazyvgrid, /swiftui/lazyhgrid, /swiftui/grid, /swiftui/outlinegroup, /swiftui/disclosuregroup
Skills: axiom-swiftui-layout, axiom-swiftui-layout-ref, axiom-swiftui-nav, axiom-swiftui-26-ref
WWDC:2020-10031、2022-10056、2023-10148、2024-10144、2025-256
文档:/swiftui/lazyvstack、/swiftui/lazyvgrid、/swiftui/lazyhgrid、/swiftui/grid、/swiftui/outlinegroup、/swiftui/disclosuregroup
技能:axiom-swiftui-layout、axiom-swiftui-layout-ref、axiom-swiftui-nav、axiom-swiftui-26-ref