形状 API
Rectangle、RoundedRectangle、Circle、Capsule、Ellipse、Color 和 ToolbarItem。
本页覆盖 Rectangle、RoundedRectangle、Circle、Capsule、Ellipse、Color 和 ToolbarItem。形状是普通 View,通常要配合 .frame(...) 才能得到稳定尺寸。
#什么时候用
| 目标 | 首选 API | 说明 |
|---|---|---|
| 矩形背景或占位 | Rectangle | 基础块状形状。 |
| 卡片背景 | RoundedRectangle | 需要圆角但不想用 .background(...) 时。 |
| 圆形头像、圆点 | Circle | 宽高相同最稳定。 |
| 胶囊按钮背景 | Capsule | 两端半圆的条状背景。 |
| 椭圆 | Ellipse | 非等宽高的椭圆。 |
| 纯色块 | Color | 用作背景层或色块视图。 |
| 工具栏项 | ToolbarItem | 放到 .toolbar([...]) 里。 |
#形状公共方法
| API | 签名 | 所属类型 |
|---|---|---|
.fill | .fill(color: ColorLike) -> Self | _Shape |
.stroke | .stroke(color: ColorLike, line_width: float = 1, **kwargs: Any) -> Self | _Shape |
已复制
import appui
def body():
card = appui.ZStack([
appui.RoundedRectangle(corner_radius=14)
.fill("secondarySystemBackground"),
appui.RoundedRectangle(corner_radius=14)
.stroke("separator", line_width=1),
appui.Text("Shape Card").font("headline"),
]).frame(height=120)
return appui.NavigationStack(
appui.VStack([card], spacing=16)
.padding()
.navigation_title("Shapes")
)
appui.run(body)
#形状签名
| API | 签名 | 分类 |
|---|---|---|
Rectangle | Rectangle() | shape |
RoundedRectangle | RoundedRectangle(corner_radius: float = 10, cornerRadius: Optional[float] = None) | shape |
Circle | Circle() | shape |
Capsule | Capsule() | shape |
Ellipse | Ellipse() | shape |
Color | Color(value: Optional[ColorLike] = None, red: Optional[float] = None, green: Optional[float] = None, blue: Optional[float] = None, opacity: float = 1.0) | shape |
ToolbarItem | ToolbarItem(placement: str = 'automatic', content: Optional[View] = None, role: Optional[str] = None) | presentation |
#颜色
fill、stroke、foreground_color、background 和 Color 都接受 AppUI 的颜色表达:
| 表达 | 示例 |
|---|---|
| 系统语义色 | "systemBlue"、"label"、"secondaryLabel"、"systemBackground"、"separator" |
| 十六进制 | "#3366CC" |
| RGB / RGBA 元组 | (0.2, 0.4, 0.8)、(0.2, 0.4, 0.8, 0.7) |
| 整数 | 0x3366CC |
已复制
import appui
def body():
return appui.NavigationStack(
appui.VStack([
appui.Color(value="systemIndigo").frame(height=28),
appui.Color(red=0.9, green=0.2, blue=0.2, opacity=0.5).frame(height=28),
appui.Circle().fill("#3366CC").frame(width=56, height=56),
appui.Capsule().stroke("systemGreen", line_width=3).frame(width=160, height=44),
appui.Ellipse().fill("systemOrange").frame(width=120, height=72),
], spacing=12)
.padding()
.navigation_title("Color")
)
appui.run(body)
#ToolbarItem
ToolbarItem 必须放在 .toolbar([...]) 中。placement 使用 AppUI 的 snake_case 名称:"automatic"、"navigation_bar_leading"、"navigation_bar_trailing"、"bottom_bar"、"principal"、"keyboard"。
已复制
import appui
def close_page():
appui.dismiss()
def body():
return appui.NavigationStack(
appui.Text("Toolbar content")
.padding()
.navigation_title("Toolbar")
.toolbar([
appui.ToolbarItem(
placement="navigation_bar_trailing",
content=appui.Button(
action=close_page,
content=appui.Label("Done", system_image="checkmark"),
),
role="close",
)
])
)
appui.run(body, presentation="sheet")
#与 Path / Canvas 的边界
| API | 不同点 |
|---|---|
Rectangle / Circle 等形状 | 原生常见形状,适合背景、边框、圆点、胶囊。 |
Path | 自定义矢量路径,适合不规则形状、曲线和弧。 |
Canvas | 命令式绘图表面,适合混合多种图元、文字和渐变。 |
.background(...) | 更适合普通卡片背景;不需要额外 ZStack。 |
已复制
import appui
def body():
commands = [
{"move": [50, 0]},
{"line": [100, 90]},
{"line": [0, 90]},
{"close": True},
]
return appui.NavigationStack(
appui.VStack([
appui.RoundedRectangle(corner_radius=8)
.fill("systemBlue")
.frame(width=120, height=64),
appui.Path(commands=commands, fill="systemOrange", stroke="label", line_width=2)
.frame(width=120, height=100),
], spacing=16)
.padding()
.navigation_title("Shape vs Path")
)
appui.run(body)
#常见错误
| 错误 | 正确做法 |
|---|---|
形状不设 .frame(...),显示尺寸不可控。 | 给形状明确宽高或高度。 |
| 圆形宽高不一致。 | Circle().frame(width: height:) 使用相同宽高;非圆用 Ellipse。 |
卡片背景都用 ZStack + RoundedRectangle。 | 普通卡片直接用 .background(..., corner_radius=...) 更简单。 |
ToolbarItem 使用旧 placement 名称。 | 使用 "navigation_bar_trailing" 等 snake_case 值。 |
用 Color(...) 包语义色再传给 .fill(...)。 | .fill("systemBlue") 直接传颜色表达即可。 |