Build a UIKit app with the new design
Design 进阶 1m

用 UIKit 构建新设计系统应用

Build a UIKit app with the new design

2025年6月9日

在 Apple 官方观看视频

一句话判断

Liquid Glass 不是换个背景色就完事的——它改变了 UIKit 组件的行为逻辑:Tab Bar 浮起来了、导航栏变透明了、搜索栏可以塞进工具栏了、按钮要分组共享玻璃背景了。好消息是重新编译就有大部分效果,坏消息是你之前做的一切 UI 自定义都得重新审视。

这场 Session 讲了什么

全面拆解 iOS 26 新设计在 UIKit 层面的适配方案,覆盖六个领域。

Tab View 和 Split View:Tab Bar 浮在内容上方,支持滚动时自动最小化(tabBarMinimizeBehavior)。新增 UITabAccessory 用于在 Tab Bar 上方放辅助视图(比如音乐 App 的迷你播放器),最小化时辅助视图动画内嵌到 Tab Bar。iPad 上 Tab Bar 和 SideBar 都用 Liquid Glass,新增 UIBackgroundExtensionView 让艺术图无缝延伸到 SideBar 后面。

导航栏和工具栏:透明背景 + Liquid Glass 按钮。系统自动按规则分组按钮——图片按钮共享玻璃背景,文字按钮和”Done/Close”按钮独占背景。用 fixedSpace 可以手动拆分组。新增 subtitle API 和 largeSubtitleView。大标题现在放在内容滚动视图顶部,和内容一起滚动。

Presentation:动态 Zoom Transition——从玻璃按钮发起的菜单/弹窗,按钮会变形融入弹窗。Action Sheet 在 iPhone 上也锚定到源视图(和 iPad 一致),不用源视图时居中显示并带取消按钮。

搜索:iPhone 上搜索栏自动移到工具栏。iPad 上可集成到导航栏尾部(类似 macOS)。Tab Bar 支持专门的 Search tab,点击展开为搜索字段。

控件:Glass 按钮(.glass() 和 .prominentGlass())。Slider 支持刻度标记(tick marks)、中性值锚点、无滑块样式。Switch 和 Segmented Control 的拇指有 Liquid Glass 交互效果。

自定义 Glass:UIGlassEffect + UIVisualEffectView。支持 tint color、isInteractive 交互效果、自动明暗模式切换。UIGlassContainerEffect 让多个 Glass 视图在靠近时自动融合。

值得深挖的点

按钮分组的自动规则需要理解透

系统不是随便分组的。规则是:图片按钮之间共享背景;多项目组(buttonGroup)共享背景;文字按钮、系统”Done/Close”、prominent 样式按钮独占背景。这个规则在大部分情况下是合理的,但如果你想要更细粒度的控制,要用 fixedSpace 手动拆分。

一个反模式是用 flexibleSpace 均匀分布工具栏按钮——默认情况下每个 flexibleSpace 都会分隔背景。如果想保持分组但均匀分布,必须设置 hidesSharedBackground = false。

BackgroundExtensionView 的正确用法

这个组件解决的是”艺术图延伸到 SideBar 后面”的问题。输入是一个 contentView(通常是 UIImageView),它会被自动延伸填充 Safe Area 之外的空白区域。关键是:延伸只发生在 Safe Area inset 为正的边缘(顶部的导航栏、Leading 的 SideBar)。

不能延伸的内容(比如节目描述文字)要作为 extensionView 的兄弟视图而不是子视图——否则也会被延伸效果影响。如果不需要顶部延伸(比如导航栏内容很少),可以关掉自动布局(automaticallyPlacesContentView = false)手动定位 contentView。

UIGlassContainerEffect 的融合动画

多个 Glass 视图放在同一个 UIGlassContainerEffect 容器里时,靠近会像水滴一样融合,重叠会合并成一个形状。用 spacing 属性控制开始融合的距离。如果要拆分,先把它们放在同一位置不动画,然后一起动画离开。

这个效果的关键约束是:容器会强制所有子 Glass 视图使用统一的自适应策略——即使它们在不同背景下,外观也保持一致。

代码片段

Tab Bar 滚动最小化 + 辅助视图

// 设置 Tab Bar 滚动行为
tabBarController.tabBarMinimizeBehavior = .onScrollDown

// 添加迷你播放器到 Tab Bar 上方
let miniPlayer = MiniPlayerView()
let accessory = UITabAccessory(contentView: miniPlayer)
tabBarController.bottomAccessory = accessory

// 监听辅助视图内嵌状态
func updateMiniPlayer() {
    let env = traitCollection.tabAccessoryEnvironment
    if env.isInline {
        // 内嵌模式:隐藏部分控件
        miniPlayer.hideSecondaryControls()
    } else {
        miniPlayer.showSecondaryControls()
    }
}

坑:TabAccessoryEnvironment 的变化需要通过 traitCollection 观察,不要自己写定时器去检测。

自定义 Glass 按钮

func createGlassButton(title: String, tint: UIColor?) -> UIButton {
    let button = UIButton()
    button.setTitle(title, for: .normal)
    var config = UIButtonConfiguration.glass()
    if let tint {
        config = UIButtonConfiguration.prominentGlass()
        button.tintColor = tint
    }
    button.configuration = config
    return button
}

// 多个 Glass 视图融合
let container = UIVisualEffectView(effect: UIGlassContainerEffect(spacing: 12))
let button1 = createGlassButton(title: "Share", tint: nil)
let button2 = createGlassButton(title: "Info", tint: nil)
container.contentView.addSubview(button1)
container.contentView.addSubview(button2)
// 靠近时自动融合

坑:Glass 的 materialize/dematerialize 动画只在设置 effect 属性时触发——用 alpha 隐藏/显示不会触发这个动画。始终通过设置 effect 为 nil 来移除 Glass。

搜索栏集成到工具栏

// iPhone: 搜索栏放在工具栏
let searchItem = UIBarButtonItem(searchBarPlacement: searchBar)
navigationItem.rightBarButtonItems = [searchItem, shareItem]

// iPad: 搜索栏集成到导航栏尾部
navigationItem.searchBarPlacementAllowsExternalIntegration = true

// Tab Bar 的 Search Tab
let searchTab = UITab(title: "Search", image: UIImage(systemName: "magnifyingglass"),
                       viewController: searchVC)
searchTab.automaticallyActivateSearch = true
tabBarController.tabs = [homeTab, libraryTab, searchTab]

坑:searchBarPlacementBarButtonItem 会根据可用空间自动决定是展开为搜索字段还是显示为工具栏按钮——不要手动控制这个行为。

最佳实践

第一步永远是重新编译。大部分 Liquid Glass 效果会在编译后自动生效——Tab Bar 浮起、导航栏透明、控件新外观。不要急着改代码,先看看自动适配的效果再决定哪些需要调整。

清理旧的自定义样式。如果你之前用了 UIBarAppearance 或 backgroundColor 自定义导航栏/工具栏外观,现在要移除它们——它们会干扰 Glass 效果。同样,之前为了区分按钮而设置的自定义颜色,现在系统自动处理分组了,手动设置可能适得其反。

Scroll Edge Effect 是新的关键概念。滚动视图在导航栏/工具栏下方会自动应用视觉处理以保证可读性。如果你有自定义的浮动容器覆盖在滚动视图边缘,用 ScrollEdgeElementContainerInteraction 把 edge effect 插到浮动容器后面——否则浮动容器下方的文字会不可读。

还有什么值得关注

  • Slider 的 TrackConfiguration 支持 allowsTickValuesOnly——限制只能选刻度值,适合离散选项(音量等级、速度档位)。
  • Slider 的 neutralValue 可以锚定在任意位置(不一定是最小值),填充色显示当前值和中性值的差值。
  • 无滑块样式(thumbless)的 Slider 看起来像进度条,适合媒体播放时不分散注意力。
  • 动态 Zoom Transition 从 iOS 16 的 Zoom Transition 演化而来,现在 Glass 按钮作为发起源时按钮会变形融入弹窗——这是自动的,不需要额外代码。
  • UIGlassEffect 的 cornerConfiguration 支持 .containerRelative,自动根据与容器边角的距离调整圆角半径——保持同心圆角。
Design SwiftUI