AppUI UI 模式
按页面类型选择 Form、List、NavigationStack、TabView 和媒体承载。
这篇文档帮你先选对页面结构,再进入具体 API。已经知道 API 名时,直接查 AppUI API 地图。
#先记住 4 条规则
- 先定页面结构,再定控件。
- 设置和编辑优先
Form + Section,动态数据优先List + ForEach。 - 多页面优先
NavigationStack + NavigationLink,主分区优先TabView + Tab。 - 默认使用原生结构;只有视频、地图、WebView、相机、Chart、Canvas、游戏化首屏这类场景才使用自定义承载。
#最小模式示例
已复制
import appui
items = [
{"id": "inbox", "title": "收件箱", "count": 12},
{"id": "today", "title": "今日任务", "count": 5},
{"id": "done", "title": "已完成", "count": 32},
]
def item_key(item):
return item["id"]
def detail_view(item):
return appui.Form([
appui.Section(item["title"], [
appui.LabeledContent("Count", value=str(item["count"])),
])
]).navigation_title(item["title"])
def row_view(item):
return appui.NavigationLink(
destination=detail_view(item),
label=appui.HStack([
appui.Text(item["title"])
.frame(max_width=appui.infinity, alignment="leading"),
appui.Text(str(item["count"])).foreground_color("secondaryLabel"),
]),
)
def body():
return appui.NavigationStack(
appui.List([
appui.Section("分区", [
appui.ForEach(items, row_builder=row_view, key=item_key),
]),
]).navigation_title("UI 模式")
)
appui.run(body)
预期效果:列表显示三个分区,点击任一行进入对应详情页。
#按页面选择结构
| 页面类型 | 推荐结构 | 适合 |
|---|---|---|
| 单页工具 | NavigationStack + VStack | 计算器、转换器、小查询页 |
| 设置页 | NavigationStack + Form + Section | 开关、输入、选择器、账号配置 |
| 列表页 | NavigationStack + List + ForEach | 任务、笔记、记录、搜索结果 |
| 列表详情 | NavigationStack + NavigationLink | 课程、商品、文档、条目详情 |
| 多主分区 | TabView + Tab | 首页、记录、设置、统计 |
| 底部常驻状态条 | TabView + .tab_view_bottom_accessory + .sheet | 音乐、播客、下载、录音、导航 |
| 仪表盘 | ScrollView + LazyVGrid + Chart | KPI、日报、趋势图、监控 |
| 媒体页 | VideoPlayer / MapView / WebView | 视频、地图、网页和富内容 |
| 自定义绘制 | Canvas + DrawingContext + Path | 轻量绘图、签名板、图形面板 |
#高频能力入口
| 能力 | 常见场景 | 继续阅读 |
|---|---|---|
NavigationStack | 页面 push、详情页、设置页 | 导航与页面结构 |
NavigationLink | 列表进详情、设置项进入子页 | 导航与页面结构 |
NavigationPath | 程序化跳转、返回、带参数详情 | 导航与页面结构 |
TabView / Tab | 首页、记录、设置等主分区 | 导航与页面结构 |
.tab_view_bottom_accessory + .sheet | 底部状态条点击后打开原生面板 | 导航参考 |
Form / Section | 设置、资料编辑、筛选条件 | 布局系统 |
TextField / SecureField | 单行输入、密码、API Key | 控件 API |
Toggle / Picker / Slider | 开关、模式、连续数值 | 控件 API |
List / ForEach | 动态行、分组数据、原生列表 | 布局系统 |
ContentUnavailableView | 空状态、无结果、无权限提示 | 数据展示 |
.searchable / .refreshable | 搜索过滤、下拉刷新 | 交互与回调 |
PhotoPicker / FileImporter | 选图、导入 PDF/CSV/文本 | 媒体与系统集成 |
CameraPicker / MapView / WebView | 拍照、地图、网页 | 媒体与系统集成 |
Chart / Canvas / Path | 数据看板、自定义绘制 | 图表与绘图 |
VideoPlayer / AsyncImage | 视频播放、远程封面 | 媒体与系统集成 |
#反模式速查
- 不要用一个巨大
VStack承载整页;内容会变多时用List、Form或ScrollView。 - 不要在
List行里放复杂媒体承载;视频、地图、WebView 应该放在稳定页面区域。 - 不要把所有编辑逻辑塞进列表行;详情页或表单页负责局部编辑。
- 不要把全局播放、下载、录音状态硬塞成一个独立 Tab;需要常驻底部状态时用
.tab_view_bottom_accessory显示紧凑条,再用.sheet展开详情。 - 不要用颜色硬模拟主题;优先使用
systemBackground、label、secondaryLabel。 - 不要把网络、权限、文件写入
body();放到按钮、刷新或明确加载动作。
#需求描述模板
描述一个 AppUI MiniApp 时,最好一次说清:
- 这是一个
appuiMiniApp。 - 有几个页面,每页负责什么。
- 每页是列表、表单、详情、仪表盘还是媒体页。
- 需要哪些状态、空态、错误态和加载态。
- 需要哪些系统能力、权限、保存或导出路径。
#失败路径
- 页面越来越乱:先回到“按页面选择结构”,不要先堆控件。
- 设置页不像原生:改成
Form + Section。 - 列表搜索后错行:给
ForEach提供稳定业务 key。 - 动画或媒体卡顿:确认是否应该用
scene、VideoPlayer、Canvas或专门媒体区域。
#API 参考
按任务查 API 见 AppUI API 地图。需要判断运行时时,先看 运行时选择。
#相关文档
| 文档 | 用途 |
|---|---|
| 快速上手 | 四个可预览示例串起最小闭环。 |
| AppUI API 地图 | 按任务查 30 项高频 API。 |
| 原生能力入口 | AppUI 页面里调用 iOS 原生模块。 |
| 开发排错 | 空白页、按钮无效、输入不更新等问题。 |