UI 组件

Core/UI 基础组件、Toast 与触感反馈。

Core/UI/ 是应用的组件库——带品牌样式、可复用的 SwiftUI 视图,每个功能都由它们组合 而成,从而让各屏幕保持一致,重塑样式也只需一处改动。本页盘点这些组件,指引你到能渲染 每个组件的实时画廊,并覆盖两套全应用级反馈系统(Toast 与触感)。它们全都消费 主题令牌

实时画廊

看全貌最快的方式是运行中应用里的 Component 标签页ComponentGalleryView 直接 从 ComponentCatalog 渲染,点按一行会推入该组件的可交互演示(ComponentDetailView)。 它是参考实现——并且与应用其余部分不同,它按设计仅为英文(文案是目录里的纯字符串, 而非 Localizable.xcstrings)。

画廊完全离线可用、无需任何密钥——它属于安装中"组件画廊 标签页离线可用"的检查项。

组件清单

按画廊相同的方式分组(ComponentGroup):

控件(Controls)

组件是什么
AppButton带品牌样式的按钮,4 种变体(primary / secondary / destructive / text),含 isLoading / isDisabled / 可选图标 / fullWidth
ThemeToggle绑定到 ThemeController 的分段 Picker(系统 / 浅色 / 深色)。

输入(Inputs)

组件是什么
AppTextField带前置图标、密文输入、内联错误、焦点控制的带标签输入框。它持有其值——绑定一个 @State 字符串。
PasswordStrengthBar纯由密码字符串驱动的三段式强度条;为空时隐藏。
OTPInputView六格一次性验证码输入;过滤非数字,通过 .oneTimeCode 自动填充,第六位落定时触发 onComplete

容器(Containers)

组件是什么
AppCard分组表面卡片(appGroupedSurface、圆角),包裹任意内容。
SectionHeader分组区块上方的大写眉标,iOS "设置"风格。
FlowLayout一个 Layout,把标签/徽章换行排列,而非滚出屏幕。

反馈:UiState 三件套

这三个渲染视图模型 UiState<T> 的各个分支(见架构):

组件用于
LoadingState.loading——居中转圈 + 可选说明
ErrorState.error——图标、消息、可选重试
EmptyState.data([])——图标、标题、消息、可选操作

外加 OfflineBanner——一条接入 NetworkObserver 的顶部 细横幅,以及 ThemeToggle(也算控件)。

媒体(Media)

组件是什么
RemoteImageKingfisher KFImage 的薄封装(内存 + 磁盘缓存、淡入、重试一次)。要更换图片库,只改这一个文件。见存储

组合一个屏幕

组件可预期地拼合到一起——对视图模型的状态做 switch,再依赖容器:

struct ExampleView: View {
    @Environment(LocaleController.self) private var locale
    @State private var viewModel: ExampleViewModel

    var body: some View {
        Group {
            switch viewModel.state {
            case .idle, .loading:
                LoadingState(message: locale.t("common.loading"))
            case .error(let message):
                ErrorState(message: message) { Task { await viewModel.load() } }
            case .data(let items) where items.isEmpty:
                EmptyState(icon: "tray", title: locale.t("example.empty"))
            case .data(let items):
                ScrollView {
                    ForEach(items) { item in
                        AppCard { Text(item.title).font(.appHeadline) }
                    }
                }
            }
        }
    }
}

注意那些 locale.t(...) 调用——面向用户的文案始终走本地化 辅助方法。

Toast

ToastControllerCore/Toast/)是一个 @MainActor @Observable,通过 ToastHostRootView 中作为浮层挂载一次。从任何地方用 AppEnvironment 上的控制器抛出一条 瞬时消息:

@Environment(AppEnvironment.self) private var env
// …
env.toast.show(locale.t("todos.cleared"), variant: .success)

三种变体(info / success / error)决定图标与配色;successerror 还会 自动触发相应触感。Toast 在其时长后自动消失(默认 3 秒),可点按关闭,新的一条会取消 上一条的计时。

触感(Haptics)

Haptics.sharedCore/Haptics/)是一个 @MainActor 单例,用意图命名的方法封装了 UIFeedbackGenerator 家族:

Haptics.shared.selection()   // 选择器 / 分段切换
Haptics.shared.light()       // 轻微点按
Haptics.shared.medium()
Haptics.shared.heavy()
Haptics.shared.success()     // 通知反馈
Haptics.shared.warning()
Haptics.shared.error()

在你确知即将触发触感的时刻之前(例如 .onAppear 中)调用 Haptics.shared.prepare(), 以预热生成器、降低首次触发延迟。Toast 已会触发 success/error 触感,因此你很少直接 调用它们。

相关页面

On this page