axiom-swiftui-containers-ref by charleswiltgen/axiom
npx skills add https://github.com/charleswiltgen/axiom --skill axiom-swiftui-containers-ref堆栈、网格、大纲和滚动增强功能。适用于 iOS 14 至 iOS 26。
来源:WWDC 2020-10031, 2022-10056, 2023-10148, 2024-10144, 2025-256
| 使用场景 | 容器 | iOS |
|---|---|---|
| 固定视图垂直/水平排列 | VStack / HStack | 13+ |
| 视图重叠 | ZStack | 13+ |
| 大型可滚动列表 | LazyVStack / LazyHStack | 14+ |
| 多列网格 | LazyVGrid | 14+ |
| 多行网格(水平) | LazyHGrid | 14+ |
| 静态网格,精确对齐 | Grid | 16+ |
| 分层数据(树状) | 带 children: 的 List |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 14+ |
| 自定义层次结构 | OutlineGroup | 14+ |
| 显示/隐藏内容 | DisclosureGroup | 14+ |
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
HStack {
Text("Left")
Spacer()
Text("Right")
}
Spacer(minLength: 20) // 最小尺寸
仅在可见时渲染子视图。在 ScrollView 内部使用。
ScrollView {
LazyVStack(spacing: 0) {
ForEach(items) { item in
ItemRow(item: item)
}
}
}
ScrollView {
LazyVStack(pinnedViews: [.sectionHeaders]) {
ForEach(sections) { section in
Section(header: SectionHeader(section)) {
ForEach(section.items) { item in
ItemRow(item: item)
}
}
}
}
}
具有精确对齐的非惰性网格。一次性加载所有视图。
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(_:) — 覆盖列对齐方式Grid {
GridRow {
Text("Header").gridCellColumns(2)
}
GridRow {
Text("Left")
Text("Right").gridColumnAlignment(.trailing)
}
}
垂直滚动网格。定义 列;行无限增长。
let columns = [
GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible())
]
ScrollView {
LazyVGrid(columns: columns, spacing: 16) {
ForEach(items) { item in
ItemCard(item: item)
}
}
}
水平滚动网格。定义 行;列无限增长。
let rows = [GridItem(.fixed(100)), GridItem(.fixed(100))]
ScrollView(.horizontal) {
LazyHGrid(rows: rows, spacing: 16) {
ForEach(items) { item in
ItemCard(item: item)
}
}
}
| 尺寸 | 行为 |
|---|---|
.fixed(CGFloat) | 精确宽度/高度 |
.flexible(minimum:maximum:) | 等分填充空间 |
.adaptive(minimum:maximum:) | 创建尽可能多的项目以适应空间 |
// Adaptive: 响应式列数
let columns = [GridItem(.adaptive(minimum: 150))]
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)
用于在 List 之外的自定义分层布局。
List {
ForEach(canvases) { canvas in
Section(header: Text(canvas.name)) {
OutlineGroup(canvas.graphics, children: \.children) { graphic in
GraphicRow(graphic: graphic)
}
}
}
}
@State private var isExpanded = false
DisclosureGroup("高级选项", isExpanded: $isExpanded) {
Toggle("启用功能", isOn: $feature)
Slider(value: $intensity)
}
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()
}
}
}
ScrollView(.horizontal, showsIndicators: false) {
LazyHStack(spacing: 16) {
ForEach(items) { item in
CarouselCard(item: item).frame(width: 280)
}
}
.padding(.horizontal)
}
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)
| 大小 | 可滚动? | 使用 |
|---|---|---|
| 1-20 | 否 | VStack/HStack |
| 1-20 | 是 | ScrollView 内的 VStack/HStack |
| 20-100 | 是 | LazyVStack/LazyHStack |
| 100+ | 是 | LazyVStack/LazyHStack 或 List |
| 网格 <50 | 否 | Grid |
| 网格 50+ | 是 | LazyVGrid/LazyHGrid |
缓存 GridItem 数组 — 在 body 外部定义:
struct ContentView: View {
let columns = [GridItem(.adaptive(minimum: 150))] // ✅
var body: some View {
LazyVGrid(columns: columns) { ... }
}
}
ScrollView(.horizontal) {
LazyHStack {
ForEach(photoSets) { set in
ScrollView(.vertical) {
LazyVStack {
ForEach(set.photos) { PhotoView(photo: $0) }
}
}
}
}
}
相对于滚动容器调整视图大小。
ScrollView(.horizontal) {
LazyHStack {
ForEach(cards) { card in
CardView(card: card)
.containerRelativeFrame(.horizontal, count: 3, span: 1, spacing: 16)
}
}
}
启用吸附效果。
ScrollView(.horizontal) {
LazyHStack {
ForEach(items) { ItemCard(item: $0) }
}
.scrollTargetLayout()
}
.scrollTargetBehavior(.viewAligned)
跟踪最顶部的可见项目。要求每个项目都有 .id()。
@State private var position: Item.ID?
ScrollView {
LazyVStack {
ForEach(items) { item in
ItemRow(item: item).id(item.id)
}
}
}
.scrollPosition(id: $position)
.scrollTransition { content, phase in
content
.opacity(1 - abs(phase.value) * 0.5)
.scaleEffect(phase.isIdentity ? 1.0 : 0.75)
}
.onScrollGeometryChange(for: Bool.self) { geo in
geo.contentOffset.y < geo.contentInsets.top
} action: { _, isTop in
showBackButton = !isTop
}
VideoPlayer(player: player)
.onScrollVisibilityChange(threshold: 0.2) { visible in
visible ? player.play() : player.pause()
}
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
每周安装量
115
仓库
GitHub 星标数
610
首次出现
2026年1月21日
安全审计
安装于
opencode100
codex94
claude-code91
gemini-cli90
github-copilot88
cursor87
Stacks, grids, outlines, and scroll enhancements. iOS 14 through iOS 26.
Sources : WWDC 2020-10031, 2022-10056, 2023-10148, 2024-10144, 2025-256
| Use Case | Container | iOS |
|---|---|---|
| Fixed views vertical/horizontal | VStack / HStack | 13+ |
| Overlapping views | ZStack | 13+ |
| Large scrollable list | LazyVStack / LazyHStack | 14+ |
| Multi-column grid | LazyVGrid | 14+ |
| Multi-row grid (horizontal) | LazyHGrid | 14+ |
| Static grid, precise alignment | Grid | 16+ |
| Hierarchical data (tree) | List with children: | 14+ |
| Custom hierarchies | OutlineGroup | 14+ |
| Show/hide content | DisclosureGroup | 14+ |
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
HStack {
Text("Left")
Spacer()
Text("Right")
}
Spacer(minLength: 20) // Minimum size
Render children only when visible. Use inside ScrollView.
ScrollView {
LazyVStack(spacing: 0) {
ForEach(items) { item in
ItemRow(item: item)
}
}
}
ScrollView {
LazyVStack(pinnedViews: [.sectionHeaders]) {
ForEach(sections) { section in
Section(header: SectionHeader(section)) {
ForEach(section.items) { item in
ItemRow(item: item)
}
}
}
}
}
Non-lazy grid with precise alignment. Loads all views at once.
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
Grid { GridRow { Text("Header").gridCellColumns(2) } GridRow { Text("Left") Text("Right").gridColumnAlignment(.trailing) } }
Vertical-scrolling grid. Define columns ; rows grow unbounded.
let columns = [
GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible())
]
ScrollView {
LazyVGrid(columns: columns, spacing: 16) {
ForEach(items) { item in
ItemCard(item: item)
}
}
}
Horizontal-scrolling grid. Define rows ; columns grow unbounded.
let rows = [GridItem(.fixed(100)), GridItem(.fixed(100))]
ScrollView(.horizontal) {
LazyHGrid(rows: rows, spacing: 16) {
ForEach(items) { item in
ItemCard(item: item)
}
}
}
| Size | Behavior |
|---|---|
.fixed(CGFloat) | Exact width/height |
.flexible(minimum:maximum:) | Fills space equally |
.adaptive(minimum:maximum:) | Creates as many as fit |
// Adaptive: responsive column count
let columns = [GridItem(.adaptive(minimum: 150))]
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)
For custom hierarchical layouts outside List.
List {
ForEach(canvases) { canvas in
Section(header: Text(canvas.name)) {
OutlineGroup(canvas.graphics, children: \.children) { graphic in
GraphicRow(graphic: graphic)
}
}
}
}
@State private var isExpanded = false
DisclosureGroup("Advanced Options", isExpanded: $isExpanded) {
Toggle("Enable Feature", isOn: $feature)
Slider(value: $intensity)
}
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()
}
}
}
ScrollView(.horizontal, showsIndicators: false) {
LazyHStack(spacing: 16) {
ForEach(items) { item in
CarouselCard(item: item).frame(width: 280)
}
}
.padding(.horizontal)
}
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)
| Size | Scrollable? | Use |
|---|---|---|
| 1-20 | No | VStack/HStack |
| 1-20 | Yes | VStack/HStack in ScrollView |
| 20-100 | Yes | LazyVStack/LazyHStack |
| 100+ | Yes | LazyVStack/LazyHStack or List |
| Grid <50 | No | Grid |
| Grid 50+ | Yes | LazyVGrid/LazyHGrid |
Cache GridItem arrays — define outside body:
struct ContentView: View {
let columns = [GridItem(.adaptive(minimum: 150))] // ✅
var body: some View {
LazyVGrid(columns: columns) { ... }
}
}
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:
ScrollView(.horizontal) { LazyHStack { ForEach(photoSets) { set in ScrollView(.vertical) { LazyVStack { ForEach(set.photos) { PhotoView(photo: $0) } } } } } }
Size views relative to scroll container.
ScrollView(.horizontal) {
LazyHStack {
ForEach(cards) { card in
CardView(card: card)
.containerRelativeFrame(.horizontal, count: 3, span: 1, spacing: 16)
}
}
}
Enable snapping.
ScrollView(.horizontal) {
LazyHStack {
ForEach(items) { ItemCard(item: $0) }
}
.scrollTargetLayout()
}
.scrollTargetBehavior(.viewAligned)
Track topmost visible item. Requires.id() on each item.
@State private var position: Item.ID?
ScrollView {
LazyVStack {
ForEach(items) { item in
ItemRow(item: item).id(item.id)
}
}
}
.scrollPosition(id: $position)
.scrollTransition { content, phase in
content
.opacity(1 - abs(phase.value) * 0.5)
.scaleEffect(phase.isIdentity ? 1.0 : 0.75)
}
.onScrollGeometryChange(for: Bool.self) { geo in
geo.contentOffset.y < geo.contentInsets.top
} action: { _, isTop in
showBackButton = !isTop
}
VideoPlayer(player: player)
.onScrollVisibilityChange(threshold: 0.2) { visible in
visible ? player.play() : player.pause()
}
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
Weekly Installs
115
Repository
GitHub Stars
610
First Seen
Jan 21, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode100
codex94
claude-code91
gemini-cli90
github-copilot88
cursor87
iOS Swift开发指南:SwiftUI、Combine、async/await构建高性能原生应用
890 周安装
使用 shadcn/ui 和 Radix Primitives 构建无障碍 UI 组件库 - CVA 变体与 OKLCH 主题指南
281 周安装
阿里云OSS ossutil 2.0 测试指南:验证AK配置与存储桶操作
278 周安装
ce:plan 技术方案规划工具 - 定义如何构建软件,生成实施方案
71 周安装
Web Browser Skill:极简CDP工具,自动化网页导航、JS执行与Cookie处理
281 周安装
Notion研究文档自动化工具:AI驱动的研究整理与报告生成工作流
279 周安装
Segment CDP 客户数据平台使用指南:Analytics.js与Node.js追踪最佳实践
282 周安装