大多数浏览器和
Developer App 均支持流媒体播放。
-
使用全新设计系统构建 UIKit App
更新你的 UIKit App,以便充分利用全新设计系统。我们将深入探索标签视图、分屏浏览、栏、演示文稿、搜索和控制项等方面的主要变化,并向你展示如何在自定 UI 中使用 Liquid Glass。为了充分从这个视频中获益,建议你先观看“了解全新设计系统”以获取一般性设计指导。
章节
- 0:00 - 简介
- 1:55 - 标签视图和分屏浏览
- 7:19 - 导航与工具栏
- 13:31 - 内容呈现形式
- 15:18 - 搜索
- 17:24 - 控件
- 19:15 - 自定元素
- 25:01 - 后续步骤
资源
相关视频
WWDC25
WWDC24
-
搜索此视频…
大家好 欢迎观看“使用全新设计 系统构建 UIKit App” 我叫 Sanaa 是 UIKit 团队的工程师 在本视频中 我将向你展示 如何采用新设计 并在 App 中运用 Liquid Glass
iOS 26 引入了全新精美的设计 更新了整个系统中材质和控件的 外观和使用感受 此次设计的核心是一种新材质 名为 Liquid Glass 它会呈现出半透明、灵动的质感 在整个系统中 UIKit 的组件和材质 已经更新应用了 Liquid Glass
如果你使用新的 SDK 重新编译 App 就会展示出全新外观 如果你还没开始体验 我强烈建议你观看设计视频 “了解 Liquid Glass”和 “使用 Liquid Glass 设计系统 进行设计” 以简要了解 这个新设计系统的最佳实践
首先 我将介绍标签视图和分屏浏览 如何采用这个新设计系统 以及悬浮在内容上方
然后 我会介绍导航栏和工具栏的 新外观和行为 它们现在采用透明设计 包含 Liquid Glass 按钮 并为内容提供更多空间
之后 我将介绍呈现效果的更新内容 包括更新的缩放过渡 以及警报和操作表单的新行为
然后 我会介绍 搜索体验的更新内容 以及搜索栏定位的更多选项
我会介绍按钮、开关和滑块等控件 最后介绍如何 在自定 UI 元素中应用 Liquid Glass 外观和使用感受
现在 我先来介绍标签视图 和分屏浏览
UITabBarController 和 UISplitViewController 已经更新应用了 新的 Liquid Glass 外观
标签栏会在 App 中 提供持续可见的顶层导航功能 让你的 App 内容一目了然 并帮助用户在不同部分之间 快速切换 使用这个新设计 iPhone 上的标签栏 会悬浮在内容上方
并且可以配置滚动时最小化 让你能够专注于查看内容
要实现标签栏滚动时最小化 可使用 tabBarMinimizeBehavior 设置目标方向 这里的 TV App 已设置为 .onScrollDown 向相反方向滚动时 标签栏就会重新展开
标签栏上方可以显示补充视图 比如“音乐”App 的迷你播放器 使用 UITabBarController 可在标签栏上方显示补充视图 并让它们的外观保持一致 当标签栏最小化时 补充视图就会向下移动 与标签栏并排显示
要设置底部的补充视图 可使用 contentView 创建 UITabAccessory 然后设置 UITabBarController 上的 bottomAccessory 属性
当补充视图与标签栏并排显示时 显示空间就会更少 为了适应有限的空间 这里的“音乐”App 就隐藏了 迷你播放器的一些媒体控件
要调整补充视图 可注册观察 tabAccessoryEnvironment 特征变化 确认补充视图是否与标签栏 并排显示 如果有需要 可更新视图
你也可以使用 updateProperties 将补充视图更新为 自动特征追踪行为
要进一步了解自动特征追踪 以及新 updateProperties 方法 请观看“UIKit 的新功能”讲座
iPad 上的标签栏和边栏 也更新应用了 Liquid Glass 使用 UITabBarController 它们会悬浮在 App 内容的上方 应用 UITab 和 UITabGroup 你的 App 就会自动适应 用户就能在 iPad 上 切换标签栏和边栏 请观看 WWDC24 讲座 “提升 iPadOS 中的标签页 和边栏使用体验” 以及 WWDC25 讲座 “让你的 UIKit App 更加灵活” 了解更多信息
融入新设计 当下方出现 与主滚动视图相匹配的醒目内容时 边栏就会更美观 iOS 26 上的 TV App 很好地展示了这个效果 插图几乎铺满了整个屏幕 并且处于边栏下方 插图保持居中状态且清晰可见 这种效果在 iOS 26 的 很多 App 中应用 使用新的 UIBackgroundExtensionView 你的 App 也会非常美观
扩展视图应覆盖整个显示宽度 包括边栏的前置安全嵌入区域 你提供的内容视图就是效果的输入 例如 当输入为图像视图时 它位于视图层次结构中 经过无缝扩展可填满整个空白区域
你可根据需要使用这个特殊效果 页面底部的剧集列表等部分 无需扩展就可在边栏下方自然滚动
插图上方的元素 比如节目名称和描述 也不应该进行扩展 这些内容应该作为扩展视图的 同级元素而非子视图进行添加
显示视图控制器 已有一个海报插图的图像视图 要添加这个效果 请创建 backgroundExtensionView 并将这个图像视图分配给 contentView 属性 将扩展视图添加到层次结构中 最后 将 detailsView 添加为 extensionView 的同级元素 默认情况下 内容视图会填充 扩展视图的安全区域 所有设置正安全嵌入区域的边缘 都会进行扩展以填充空白区域 在本例中 这些是 导航栏和状态栏的顶部边缘 以及边栏的前置边缘 由于 TV App 导航栏中的内容不多 几乎不会覆盖插图 因此 不需要顶部的扩展效果 相反 内容视图是通过手动方式 放置在 顶部安全区域外侧的
我们再来看代码示例 了解如何手动调整效果布局 首先 在 extensionView 上将 automaticallyPlacesContentView 设置为 false 使用 AutoLayout 约束条件 将图像视图定位在屏幕顶部 然后扩展边栏下方的图像视图 为 leadingAnchor 增加约束条件 即 extensionView 的 safeAreaLayoutGuide
另外还要记得为 后置和底部锚点增加约束条件
现在 让我来介绍这个新设计中 导航栏和工具栏的外观和行为 iOS 26 中的导航栏和工具栏 同样会采用新的玻璃外观 并会悬浮在内容上方 当你指定工具栏 或导航工具栏按钮项目时 系统会自动将它们 按视觉特征进行分组 每个小组共享一种玻璃背景
默认情况下 使用图像的工具栏按钮项目 与其他图像按钮共享相同的背景 具有多个项目的按钮组 同样共享相同的背景
文本按钮、SystemItem.done、 SystemItem.close 按钮 以及 Style.prominent 按钮 都具有独立的玻璃背景 本示例直观地展示了这些规则 其中 开头的“选择”按钮 和末尾的确认按钮 以及中间的 4 个图像按钮 并未共享同一种玻璃背景 要设置导航栏 请将所有工具栏按钮项目直接分配给 navigationItem 的 rightBarButtonItems 这样设置后 就会得到 我之前提到过的默认系统行为 要将项目划分到独立的小组中 可使用 fixedSpace 项目 在本例中 我想将 shareButton 分离出来 因此 我会在 share 和 infoButton 之间插入 fixedSpace
工具栏按钮默认使用 labelColor 以提高易读性 如果需要用到颜色来传递 操作信息 就可以指定不同的色调
比如 在本例中 我会更新 flagButton 将 tintColor 设置为 systemOrange
只有旗帜符号才能指定颜色
要指定按钮背景的颜色 可将 style 设置为 prominent
之前 你可能已使用 flexibleSpace 来均匀分布工具栏中的项目 使用 Liquid Glass 默认情况下 每个 flexibleSpace 项目 会将项目之间的背景分离开来
要均匀分布项目 并将它们分入单个背景中 可使用 flexibleSpace 并将 hidesSharedBackground 设为 false
在 iOS 26 中 UINavigationItem 在导航栏中为标题和大标题区域 提供了更多的控制 这包括标题下方渲染的 新增副标题
可使用属性字符串对标题和副标题 进行精细的调整
指定自定视图以添加交互式元素
大标题现在放置在 内容滚动视图的顶部 可与工具栏下方的内容滚动查看
要保持大标题始终可见 可充分扩展导航栏下方的滚动视图
在本例中 “邮件”中的搜索字段 位于工具栏中 并使用新的副标题 API 在导航栏中显示了未读邮件的数量
在筛选电子邮件时 “邮件”中的大标题下方 会显示当前筛选按钮 在 navigationItem 上 按钮已设置为 largeSubtitleView 在导航栏中 这个按钮会显示在大标题的下方 工具栏背景是 iOS26 中的 一项新设计 现在默认为透明状态 要从导航栏和工具栏中 删除任何背景自定设置 使用 UIBarAppearance 或 backgroundColor 会干扰玻璃外观
工具栏按钮使用玻璃背景 使用布局外边距来排布 自定视图内容 可确保显示合适的间距 导航栏或工具栏下方的 所有滚动视图 会自动应用视觉处理 这能确保工具栏中的重叠内容 清晰可见 这称为“边缘效果” 这项新的边缘效果 并非只限于系统工具栏使用 你也可以配合使用 覆盖滚动视图边缘的 自定视图容器 本示例展示了 两个覆盖滚动视图底部边缘的按钮 要在这组按钮后面插入边缘效果 可创建 scrollEdgeElementContainerInteraction 分配 contentScrollView 和 edge 然后将它添加到 buttonsContainerView 对于包含大量悬浮元素的 密集型 UI 可在滚动视图的边缘上选择 hard 边缘样式 这与 iOS 18 中 标准工具栏背景的外观相似 要启用这个效果 可将边缘效果的样式设置为 .hard
iOS 18 引入了 始终交互式可中断的缩放过渡 iOS 26 为标准导航幻灯片过渡 带来了相同的流动质感
这里使用的是“备忘录”App 我可以打开一条笔记 App 会在页面过渡过程中 保持流畅响应
如果我误选了笔记 可以立即轻扫返回
也可以在过渡画面尚未完成时 就开始滚动页面 同样地 我可以立即 多次轻点返回按钮 以便快速地返回
这项功能非常实用 因为用户可以随时与 App 交互 当然 这也意味着 你的 App 需要随时准备好 响应用户交互 要了解如何正确处理可中断的过渡 请观看视频 “提升 UI 动画和过渡效果” 现在 我也可以在内容区域的 任意位置 而不只是 在前置边缘执行轻扫返回操作 新的内容轻扫返回手势 会自动检查是否存在 其他冲突的交互操作
例如 轻扫内容区域就无法返回 但在非交互式区域 则支持轻扫返回操作
要让自定手势优先于 内容轻扫返回操作 需要在 interactiveContentPopGestureRecognizer 上 设置失败条件
新的设计同样适用于呈现效果 包括新增的动态缩放过渡 当菜单或弹出窗口等呈现 源自玻璃质感按钮时 这个按钮会变形为叠加层
这能确保整个动画过程中 来源和呈现之间的 视觉连贯性
菜单会自动获取此行为 当弹出窗口来源是工具栏按钮项目时 也会呈现这个新动画 通过使用更新的缩放过渡 表单可以采用这一效果 在呈现的 viewController 上 将 preferredTransition 设置为 .zoom 然后在闭包中返回 源 barButtonItem
iOS 26 中的表单有一项更新设计 会随高度由小到大的变化 自适应调整外观 要应用新的玻璃质感外观 请删除任何自定背景
iPad 上的操作表单 锚定在源代码视图上 从 iOS 26 开始 操作表单的行为会一致 直接出现在源视图上方
在 alertController 上 务必设置 popoverPresentationController 的 sourceItem 或 sourceView 无论它显示在哪个设备上 分配 sourceView 新的过渡效果 也会自动应用于操作表单
操作表单会通过内联方式呈现 没有取消按钮 因为取消的功能会隐含于 点击任意其他区域的操作中 如果未指定源代码 操作表单会居中 并会出现取消按钮 iOS 26 会带来更紧凑的 全新搜索体验 你可以根据 App 要求 将搜索字段放置在合适的位置 iPhone 上的搜索栏 会自动移动到工具栏 这样就能轻松使用搜索字段
如果你已有工具栏 可添加 searchBarPlacementBarButtonItem 以及其他工具栏按钮 这样就能将搜索栏置于 你想要它出现的地方
可显示为扩展字段 或工具栏按钮 具体取决于可用空间
在 iPad 上 对于普遍可访问的搜索 可使用与 macOS 工具栏同样的方式 将搜索栏放置在导航栏的后置边缘 这非常适合分屏浏览 要启用此行为 可将 navigationItem 上的 searchBarPlacementAllowsExternalIntegration 设置为 true
要在切换视图的同时 保持搜索栏的可见性 可使用 UITabBarController 现在 会在侧边缘出现 一个单独的搜索标签 轻点搜索按钮时 它就会扩展成 搜索字段 其他按钮就会折叠起来
这个搜索 tabView 非常适合 放置搜索建议 默认情况下 选择其中一个建议 或轻点搜索字段 即可开始执行搜索
要在轻点搜索标签时 自动启用搜索字段 可将标签上的 automaticallyActivateSearch 设置为 true
对于专门的搜索视图 可考虑在边栏或标签栏中 加入搜索部分 搜索栏可整合到导航栏的后置边缘 与其他项目叠放在一起 或置于 iPad 标准宽度布局的 居中位置 要将搜索栏置于中央 可将 preferredSearchBarPlacement 设置为 integratedCentered 当标签栏可见时 搜索栏就会出现在它的下方
现在 我来介绍一下控件外观的更新
iOS 上的控件经过重新设计 外观和使用感受焕然一新 但整体依然与之前保持一致 UISwitch 等控件的大小略有更新 请检查你的布局是否设置为 适应大小更新 Switch 和 segmentedControl 上的 控制拇指 在交互时 会自动呈现出新的 Liquid Glass 外观
除了现有的按钮样式外 还有两个新的玻璃质感外观 可使用 UIButtonConfiguration 进行设置 使用 .glass() 配置 可获得常规的玻璃质感 使用 .prominentGlass() 就能获得 与 App 色调相一致的玻璃质感色调 对于滑块 除了在拇指图像上呈现 Liquid Glass 效果外 移动时 它们还会保留 动感和拉伸的效果 iOS 26 上的滑块现在支持刻度线 可通过 TrackConfiguration 配置 这种配置可用于设置 滑块的外观和行为 例如 要将这个速度滑块 限制为 5 个值 可将 trackConfiguration 设置为 allowsTickValuesOnly 和 5 个刻度线
滑块也可配置为使用 neutralValue 将填充滑块锚定到 移动轨道的任意位置 而不仅限于最小值端 这样 填充滑块就会显示出 特定值和中间值的差异 在本示例中 填充滑块显示的 速度选择值高于默认值 滑块也可以采用无拇指钮样式 这样在非交互状态下 就会呈现出进度条外观 这非常适合媒体播放 不会在播放媒体内容时 被大拇指效果所干扰 以上就是系统控件引入 Liquid Glass 的内容了 对于特定的用例 UIKit 还提供 API 用于采用新的 Liquid Glass 外观和使用感受 在将 Liquid Glass 用于 UI 时 需要记住 Liquid Glass 的设计意图 Liquid Glass 与其他视觉效果 并不相同 比如 UIBlurEffect 因此 它有适合使用的特定位置 Liquid Glass 的设计用途为互动层 它会悬浮在内容上方 给人一种触手可及的感觉 还会提供用户可触的主控件 因此 应该针对 App 的 关键元素应用 Liquid Glass 请尽量使用系统视图和控件 以实现最佳的体验效果
“地图”可将 Liquid Glass 应用于自定按钮 让按钮悬浮于地图上方 作为独特的控制层 它们的呈现效果很自然 应用玻璃质感可实现悬浮视效 因此 是一个非常不错的选择 当表单扩展时 地图上的按钮就会消失 这可防止玻璃元素 与其他玻璃元素重叠 并保持单层玻璃悬浮效果的 视觉完整性
要将玻璃质感应用于自定视图 可创建 UIVisualEffectView 创建新的 UIGlassEffect
在动画块中 设置 effect
使用特定材质化动画 就会出现玻璃质感
默认情况下 玻璃是胶囊形状的 要自定形状 可使用新的边角配置 API
玻璃会呈现深色和浅色的外观 它会适应选定的 userInterfaceStyle 将玻璃质感添加到 现有的玻璃容器中时 它会自动适应外观 要让边角自动适应容器 可将 cornerConfiguration 配置为 .containerRelative 当将视图移到靠近容器角落的位置时 它的圆角半径会自动调整
往远处移动时 圆角半径会逐渐减小 视图会自动保持同心效果 玻璃会根据大小调整外观
尺寸越大越不透明
越小就越透明 并且还会自动切换深色和浅色模式 以增强对比度
要添加标签和图像等内容 可使用 visualEffectView 的 contentView 标签就会根据文本颜色 自动调整以呈现生动效果 这可确保在各种背景下 内容清晰可见
使用动态颜色时 玻璃和其中的内容 将自动切换浅色或深色模式 具体取决于背景颜色
要高亮突显视图 可设置玻璃上的 .tintColor 添加动画效果以及其他玻璃属性 同时为内容应用更改 比如 textColor
要为玻璃设置自定色调 可创建新的 UIGlassEffect 分配自定 tintColor 并将 effect 设置为新的 UIGlassEffect 玻璃色调会自动适应 以呈现出生动的效果 要清除玻璃上的内容 可将内容的 alpha 值设置为 0
按钮等交互式系统元素 会响应用户互动 轻点按钮时 它会缩放和弹跳 要在自定视图中 获得相同的交互效果 可将 glassEffect 上的 isInteractive 设置为 true
最后 如果你不需要在屏幕上 呈现玻璃效果 可将 effect 设置为 nil 即可取消这个动画效果
始终优先设置 effect 属性 而非 alpha 这样可确保玻璃材质 能以合适的动画效果显现或消失 在这些示例中 只有一个视图使用 Liquid Glass 当多个元素交互时 玻璃效果会有额外的内置行为 Liquid Glass 可以无缝融合 不同的形状
要动态合并玻璃视图 可使用 UIGlassContainerEffect 配置 UIVisualEffectView 创建你的玻璃视图 并在容器 contentView 上 将它们添加为子视图 如果它们之间存在空间 就会以两个独立的视图呈现
只有相互靠近时 才会合并 这就像小水滴一样 要控制它们开始相互影响的距离 请使用 UIGlassContainerEffect 上的 spacing 属性
当动画效果的边框相互重叠后 玻璃视图会融合成独立的形状 要将玻璃分成多个元素 首先 将它们添加到相同的位置 但不加入动画效果 然后 一起移除它们的动画效果
UIGlassContainerEffect 的功能 可不止添加动画效果 它会强制执行统一的适应 玻璃会动态地适应背景 但仍然保持一致的外观
以上就是 Liquid Glass 中 UIKit 组件和材质的所有更新内容了 UIKit 提供了你需要的所有工具 可用于更新 App 设计 现在 你就可以着手 使用 Xcode 26 构建 App 了 新设计的很多内容 可直接在 App 中应用 逐屏审查 App 界面 找出哪些视图最突出
如果你已有自定控件 请判断标准 UIKit 控件 是否更合适 最后 请思考如何 借助 Liquid Glass 让特殊用例脱颖而出
期待在你采用全新设计系统后 我们能一睹你 App 的风采 感谢观看!
-
-
2:31 - Minimize tab bar on scroll
// Minimize tab bar on scroll tabBarController.tabBarMinimizeBehavior = .onScrollDown
-
3:08 - Add a bottom accessory
// Add a bottom accessory let nowPlayingView = NowPlayingView() let accessory = UITabAccessory(contentView: nowPlayingView) tabBarController.bottomAccessory = accessory
-
3:35 - Update the accessory with the tabAccessoryEnvironment trait
// Update the accessory with the trait registerForTraitChanges([UITraitTabAccessoryEnvironment.self]) { (view: MiniPlayerView, _) in let isInline = view.traitCollection.tabAccessoryEnvironment == .inline view.updatePlayerAppearance(inline: isInline) } // Automatic trait tracking with updateProperties() override func updateProperties() { super.updateProperties() let isInline = traitCollection.tabAccessoryEnvironment == .inline updatePlayerAppearance(inline: isInline) }
-
5:51 - Extend content under the sidebar
// Extend content underneath the sidebar let posterImageView = UIImageView(image: ...) let extensionView = UIBackgroundExtensionView() extensionView.contentView = posterImageView view.addSubview(extensionView) let detailsView = ShowDetailsView() view.addSubview(detailsView)
-
6:51 - Adjust the effect layout
// Adjust the effect layout let posterImageView = UIImageView(image: ...) let extensionView = UIBackgroundExtensionView() extensionView.contentView = posterImageView extensionView.automaticallyPlacesContentView = false view.addSubview(extensionView) posterImageView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ posterImageView.topAnchor.constraint(equalTo: extensionView.topAnchor), posterImageView.leadingAnchor.constraint(equalTo: extensionView.safeAreaLayoutGuide.leadingAnchor), posterImageView.trailingAnchor.constraint(equalTo: extensionView.safeAreaLayoutGuide.trailingAnchor), posterImageView.bottomAnchor.constraint(equalTo: extensionView.safeAreaLayoutGuide.bottomAnchor), ])
-
8:38 - Custom grouping
// Custom grouping navigationItem.rightBarButtonItems = [ doneButton, flagButton, folderButton, infoButton, .fixedSpace(0), shareButton, selectButton ]
-
8:53 - UIBarButtonItem tint color and style
// Tint color and style let flagButton = UIBarButtonItem(image: UIImage(systemName: "flag.fill")) flagButton.tintColor = .systemOrange flagButton.style = .prominent
-
9:10 - Toolbar with evenly distributed items in a single background
// Toolbar with evenly distributed items, grouped in a single background. let flexibleSpace = UIBarButtonItem.flexibleSpace() flexibleSpace.hidesSharedBackground = false toolbarItems = [ .init(image: UIImage(systemName: "location")), flexibleSpace, .init(image: UIImage(systemName: "number")), flexibleSpace, .init(image: UIImage(systemName: "camera")), flexibleSpace, .init(image: UIImage(systemName: "trash")), ]
-
10:15 - Titles and subtitles
// Titles and subtitles navigationItem.title = "Inbox" navigationItem.subtitle = "49 Unread"
-
10:27 - Large subtitle view
// Titles and subtitles navigationItem.title = "Inbox" navigationItem.largeSubtitleView = filterButton
-
11:20 - Edge effect for a custom container
// Edge effect’s custom container let interaction = UIScrollEdgeElementContainerInteraction() interaction.scrollView = contentScrollView interaction.edge = .bottom buttonsContainerView.addInteraction(interaction)
-
11:48 - Hard edge effect style
// Hard edge effect style scrollView.topEdgeEffect.style = .hard
-
13:55 - Morph popover from its source button
// Morph popover from its source button viewController.popoverPresentationController?.sourceItem = barButtonItem
-
14:07 - Morph sheet from bar button
// Morph sheet from bar button viewController.preferredTransition = .zoom { _ in folderBarButtonItem }
-
14:46 - Source item for action sheets
// Setting source item for action sheets alertController.popoverPresentationController?.sourceItem = barButtonItem
-
15:36 - Placing search in the toolbar
// Place search bar in a toolbar toolbarItems = [ navigationItem.searchBarPlacementBarButtonItem, .flexibleSpace(), addButton ]
-
16:01 - Universally accessible search on iPad
// Place search at the trailing edge of the navigation bar navigationItem.searchBarPlacementAllowsExternalIntegration = true
-
16:47 - Activate the search field when search bar is tapped
// Activate the search field when search bar is tapped searchTab.automaticallyActivatesSearch = true
-
17:03 - Search as a dedicated view
// Search as a dedicated view navigationItem.preferredSearchBarPlacement = .integratedCentered
-
17:52 - Buttons
// Standard glass button.configuration = .glass() // Prominent glass tintedButton.configuration = .prominentGlass()
-
18:16 - Neutral slider with 5 ticks and a neutral value
// Neutral slider with 5 ticks and a neutral value slider.trackConfiguration = .init(allowsTickValuesOnly: true, neutralValue: 0.2, numberOfTicks: 5)
-
18:59 - Thumbless slider
// Thumbless slider slider.sliderStyle = .thumbless
-
20:28 - Glass for custom views
// Adopting glass for custom views let effectView = UIVisualEffectView() addSubview(effectView) let glassEffect = UIGlassEffect() // Animating setting the effect results in a materialize animation UIView.animate { effectView.effect = glassEffect }
-
20:49 - Custom corner configuration
// Custom corner configuration UIView.animate { effectView.cornerConfiguration = .fixed(8) }
-
20:54 - Dark mode
// Adapting to dark mode UIView.animate { view.overrideUserInterfaceStyle = .dark }
-
21:02 - Adding glass to an existing glass container
// Adding glass to an existing glass container let container = UIVisualEffectView() container.effect = UIGlassEffect() container.contentView.addSubview(effectView)
-
21:08 - Container relative corners
// Container relative corners UIView.animate { effectView.cornerConfiguration = .containerRelative() effectView.frame.origin = CGPoint(x: 10, y: 10) }
-
21:23 - Container relative corners, animated
// Container relative corners UIView.animate { effectView.frame.origin = CGPoint(x: 30, y: 30) }
-
21:30 - Glass adapts based on its size
// Glass adapts based on its size UIView.animate { view.overrideUserInterfaceStyle = .light effectView.bounds.size = CGSize(width: 250, height: 88) } UIView.animate { effectView.bounds.size = CGSize(width: 150, height: 44) }
-
21:49 - Adding content to glass views
// Adding content to glass views let label = UILabel() label.text = "WWDC25" label.textColor = .secondaryLabel effectView.contentView.addSubview(label)
-
22:15 - Applying tint color to glass
// Applying tint color to glass let glassEffect = UIGlassEffect() glassEffect.tintColor = .systemBlue UIView.animate { effectView.effect = glassEffect label.textColor = .label }
-
22:33 - Using custom colors with glass
// Using custom colors with glass let glassEffect = UIGlassEffect() glassEffect.tintColor = UIColor(displayP3Red: r, green: g, blue: b, alpha: 1) UIView.animate { effectView.effect = glassEffect // Animate out the label label.alpha = 0 }
-
23:03 - Enabling interactive glass behavior
// Enabling interactive glass behavior let glassEffect = UIGlassEffect() glassEffect.isInteractive = true effectView.effect = glassEffect
-
23:20 - Animating glass out using dematerialize animation
// Animating glass out using dematerialize animation UIView.animate { effectView.effect = nil }
-
23:52 - Adding glass elements to a container
// Adding glass elements to a container let container = UIGlassContainerEffect() let containerView = UIVisualEffectView(effect: container) let glassEffect = UIGlassEffect() let view1 = UIVisualEffectView(effect: glassEffect) let view2 = UIVisualEffectView(effect: glassEffect) containerEffectView.contentView.addSubview(view1) containerEffectView.contentView.addSubview(view2)
-
24:12 - Adjusting the container spacing
// Adjusting the container spacing let containerEffect = UIGlassContainerEffect() containerEffect.spacing = 20 containerEffectView.effect = containerEffect
-
24:27 - Merging two glass views
// Merging two glass views UIView.animate { view1.frame = finalFrame view2.frame = finalFrame }
-
24:33 - Dividing glass into multiple views
// Dividing glass into multiple views UIView.performWithoutAnimation { for view in finalViews { containerEffectView.contentView.addSubview(view) view.frame = startFrame } } UIView.animate { for view in finalViews { view.frame = finalFrame(for: view) } }
-