WWDC Quick Look 💓 By SwiftGGTeam
Communicate your brand identity on iOS

Communicate your brand identity on iOS

观看原视频

Highlight

Apple 在 iOS 26 的 Liquid Glass 设计体系下,明确将 App 界面分为 UI 层和内容层:导航控件必须保持原生,品牌个性全部交给内容层表达,开发者无需在”像 iOS”和”有辨识度”之间二选一。

核心内容

以前的问题:品牌表达和原生体验总像一对冤家

很多开发者遇到过这个困境:设计师要求 App 的导航栏用品牌色、TabBar 要自定义样式,结果用户打开 App 要花几秒才能找到返回按钮。跨平台团队更痛苦——把 Web 或 Android 的设计直接搬到 iOS,用户总觉得”哪里不对”。(00:14

Apple 的态度很明确:iPhone 用户期望手机上的 App 看起来像 iOS。限制创意不是目的,减少认知负担才是。用户不会同时用你的 iOS、Android 和 Web 版本,他们只关心手里的这个 App 是否符合直觉。(01:20

iOS 26 的解法:两层模型

Liquid Glass 的引入带来了一个核心概念——把 App 看作两层:

  • UI 层:导航栏、TabBar、工具栏,负责让用户找到路
  • 内容层:滚动视图里的图片、文字、数据可视化,负责让 App 独一无二(02:36

内容层才是表达品牌的最佳位置。UI 层作为基础,帮用户快速理解怎么操作。

Gentler Streak 是一个健身 App,一眼看去全是品牌插画和数据图表,个性十足。但仔细看导航:TabBar 和顶部工具栏全是原生组件,没有魔改。(03:21

Slack 的顶部工具栏做了定制——中间放了一个显示频道信息的按钮。但按钮尺寸、浮动操作的位置、弹出行为,都和系统组件一致。(04:12

Moonlitt 是一个追踪月相的 App,没有 TabBar,界面极简。它的月相日历是一个自定义组件,但用了 Liquid Glass 背景、系统 Sheet 的同心圆边缘,和硬件圆角呼应。这个 App 独一无二,但一看就是 iOS 原生。(04:29

颜色:从导航栏搬到内容区

iOS 26 之前,很多 App 在导航栏和 TabBar 上铺满品牌色。这些控件很笨重,把内容区压缩得更小。(09:24

现在的建议是把颜色移入内容区,也就是 ScrollView 里。Liquid Glass 控件悬浮在内容上方,会动态吸取底部的品牌色。Slack 就把顶部的纯色工具栏移到了内容区,让它随滚动消失,内容可以铺满整个屏幕。(10:39

颜色要用得克制。它应该表达层级、分组或交互状态,而不是铺满整个界面。Slack 只在关键位置用色:新消息徽章、新建消息按钮、TabBar 选中态。(10:16

自定义字体:必须支持 Dynamic Type

Crumbl 这个 App 用了自己设计的 Crumbl Sans 字体,在营销和 App 的大标题里都用它。但当用户把系统字号调到最大时,App 依然可读——文字会换行,不会截断。(12:00

Dynamic Type 是辅助功能设置,但很多人把它当作日常偏好。Apple 的系统字体内置了这个能力,自定义字体需要开发者自己实现和测试。

Gentler Streak 完全使用系统字体,通过混合不同字宽和 SF Rounded 变体,实现了丰富的层级感,同时保持辨识度。(13:53

图标:自定义和 SF Symbols 都可以

NYT Cooking 用了自己的图标风格,边缘更锐利,以线型为主。这些图标用在 TabBar、工具栏和内容层里,统一且简洁,缩放后在小尺寸下依然清晰。(14:26

一个细节:NYT Cooking 的”分享”图标在 iOS、Android 和 Web 上是三个不同版本。虽然风格统一,但每个平台都遵循了该平台用户熟悉的分享范式。(14:58

不是每个 App 都需要自定义图标。SF Symbols 现在有 7000 多个符号,内置于 Xcode,支持动态缩放、辅助功能和本地化。设计师不用再导出图标库,开发者直接敲代码调用。(15:23

Logo 不要常驻导航栏

在 iOS 的语境下,用户不需要被提醒自己在用哪个 App。Logo 会占用宝贵的屏幕空间。NYT Cooking 只在主页显示 Logo,滚动时淡出。这种克制很优雅。(15:59

详细内容

让自定义字体支持 Dynamic Type

场景:使用品牌字体,同时确保用户在系统设置中放大字号时布局不崩。

Text("本周新口味:巧克力碎片")
    .font(.custom("CrumblSans-Bold", size: 24, relativeTo: .title))
    .lineLimit(nil)
    .fixedSize(horizontal: false, vertical: true)

关键点:

  • relativeTo: .title 把自定义字体绑定到系统的 .title 文本样式,用户调整系统字号时,它会按比例缩放
  • lineLimit(nil) 允许文字在空间不足时换行,而不是截断
  • .fixedSize(horizontal: false, vertical: true) 确保 SwiftUI 正确计算多行文本的高度,放大字号后不会被切断

坑:如果不加 relativeTo,字体大小写死。视障用户放大字号时,文字会重叠或溢出屏幕。

用系统上下文菜单替代自定义弹出框

场景:放弃手写的长按菜单,用系统标准组件,白嫖内置的形变动效。

struct MoonPhaseView: View {
    var body: some View {
        Image("moon_full")
            .resizable()
            .frame(width: 100, height: 100)
            .contextMenu {
                Button {
                    // 处理设置逻辑
                } label: {
                    Label("月相设置", systemImage: "gearshape")
                }

                Button(role: .destructive) {
                    // 处理删除逻辑
                } label: {
                    Label("移除观测", systemImage: "trash")
                }
            }
    }
}

关键点:

  • .contextMenu 是 SwiftUI 原生修饰符,不需要额外实现手势识别
  • 菜单会从被点击的元素”生长”出来,带有系统内置的 morphing 动画
  • role: .destructive 让删除项自动显示红色,符合系统惯例
  • 使用 Label 配合 SF Symbols,图标和文字自动对齐

坑:如果用自定义 Image 代替 systemImage,尺寸和基线没对齐的话,形变动效会很奇怪。尽量用 SF Symbols,或确保自定义图标严格遵循 24x24 且带正确的 baseline。

用 Zoom Transition 连接内容

场景:点击列表项进入详情页时,用流畅的过渡动画建立视觉关联。

struct RecipeListView: View {
    @Namespace private var animationNamespace

    var body: some View {
        NavigationStack {
            List(recipes) { recipe in
                NavigationLink(value: recipe) {
                    RecipeRow(recipe: recipe)
                        .matchedTransitionSource(id: recipe.id, in: animationNamespace)
                }
            }
            .navigationDestination(for: Recipe.self) { recipe in
                RecipeDetailView(recipe: recipe)
                    .navigationTransition(.zoom(sourceID: recipe.id, in: animationNamespace))
            }
        }
    }
}

关键点:

  • matchedTransitionSource 标记过渡的起点视图
  • navigationTransition(.zoom(...)) 在详情页定义过渡动画
  • 用户点击的列表项会平滑放大成详情页,建立清晰的”从哪来”的关联
  • 这种过渡既愉悦,又提升了交互效率

在内容区顶部铺垫品牌色,让 Liquid Glass 动态吸取

场景:把品牌色从导航栏移到 ScrollView 顶部,让悬浮的玻璃控件自然呈现品牌色调。

struct ContentView: View {
    var body: some View {
        ScrollView {
            VStack(spacing: 0) {
                // 顶部大面积品牌色区域,给 Liquid Glass 提供"底色"
                Rectangle()
                    .fill(brandGradient)
                    .frame(height: 200)

                // 实际内容
                LazyVStack {
                    ForEach(items) { item in
                        ItemRow(item: item)
                    }
                }
            }
        }
    }

    var brandGradient: LinearGradient {
        LinearGradient(
            colors: [Color.purple.opacity(0.8), Color.blue.opacity(0.6)],
            startPoint: .top,
            endPoint: .bottom
        )
    }
}

关键点:

  • 顶部放一个高度足够的彩色区域,Liquid Glass 控件悬浮在上面时会动态折射这些颜色
  • 颜色不要太碎、对比度不要太低,否则玻璃效果会显得灰暗
  • 内容区使用大面积渐变比纯色块更有层次感

核心启发

  • 做一个月相追踪 App,用全屏渐变夜空做内容层背景

    参考 Moonlitt 的做法:内容层铺满从深蓝到黑色的渐变,模拟夜空。3D 月相模型悬浮在中央,随用户位置动态变化。导航用极简的单层结构,不需要 TabBar。Liquid Glass 控件会自然吸取夜空的深蓝色调,整个界面统一且有沉浸感。入口:用 SwiftUI 的 MeshGradientLinearGradient 做背景,SceneKitRealityKit 渲染 3D 月相。

  • 做一个食谱 App,用 Zoom Transition 连接菜谱列表和详情

    参考 NYT Cooking:用户在列表页点击一张菜品图片,图片平滑放大成详情页首图。评论区从底部滑入。返回时,详情页收缩回列表中的原位置。这种过渡让”浏览-阅读”的切换非常连贯。入口:SwiftUI 的 matchedTransitionSource + navigationTransition(.zoom)

  • 做一个健身数据 App,用弹簧动画让月度数据”活”起来

    参考 Gentler Streak:月度回顾页面滚动时,每个数据卡片用 .spring(response: 0.4, dampingFraction: 0.7) 动画依次入场。运动类型用不同的 SF Symbols 变体(figure.runfigure.swim)区分。完全使用系统字体,通过字宽和字重变化建立层级。入口:SwiftUI 的 .scrollTransitionwithAnimation(.spring)

  • 做一个烘焙品牌 App,自定义字体只用在”记忆点”位置

    参考 Crumbl:设计一套品牌字体,但只在大标题(如每周新口味名称)和营销弹窗中使用。正文、按钮、导航全部用 San Francisco。这样既保留了品牌记忆点,又保证了可读性和 Dynamic Type 支持。入口:用 .custom("BrandFont", relativeTo: .largeTitle) 绑定到系统文本样式。

  • 做一个桌面小组件,用品牌配色强化用户心智

    参考 Crumbl 的 Widget:如果用户觉得你的数据有价值(如每日步数、待办清单、天气),提供一个配色柔和、辨识度高的桌面小组件。小组件本身不需要复杂交互,但它每天出现在用户主屏幕上,是最高频的品牌曝光点。入口:WidgetKit + AppIntent,设计时保持与 App 内容层一致的配色和图标风格。

关联 Session

  • Principles of great design — Apple 对 AI 时代设计责任的硬红线,以及 Agency 和 Forgiveness 的交互原则
  • SwiftUI — SwiftUI 新控件和动画 API,实现 Session 中提到的过渡和交互效果
  • UIKit modernization — UIKit 现代化改进,适合需要混合使用 UIKit 和 SwiftUI 的项目
  • Design principles — 设计原则的深度展开,与品牌表达形成互补
  • AppKit modernization — macOS 端的界面现代化,如果你的品牌需要跨 Apple 平台保持一致

评论

GitHub Issues · utterances