SwiftUI 中 iOS 26 玻璃效果的向后兼容实现
简介
iOS 26 引入了 Liquid Glass,这是 Apple 自 iOS 7 以来最重大的设计演进。这种半透明的动态材质可以反射和折射周围的内容,为导航元素和控件创造出精致的视觉效果。
虽然新的 .glassEffect() 修饰符使实现这种设计变得简单,但大多数应用仍需要支持旧版 iOS。本文将向你展示如何创建一个可复用的 View 扩展,在 iOS 26+ 上使用原生 Liquid Glass,在旧版本上降级到 .thinMaterial。
挑战
当你尝试在 iOS 26 之前的版本上使用 .glassEffect() 时,你的应用将无法编译。你需要一个解决方案:
- 在 iOS 26+ 上使用原生 Liquid Glass
- 为 iOS 18-25 提供一致的降级方案
- 保持视图代码简洁
解决方案
这是一个优雅处理两种情况的 View 扩展:
import SwiftUI
extension View {
/// 应用具有向前兼容性的玻璃效果。
/// - iOS 26+:使用原生 `.glassEffect()` 呈现 liquid glass 外观
/// - iOS 18-25:降级到 `.thinMaterial` 以保持一致性
@ViewBuilder
func glassedEffect(in shape: some Shape, interactive: Bool = false) -> some View {
if #available(iOS 26.0, *) {
self.glassEffect(interactive ? .regular.interactive() : .regular, in: shape)
.clipShape(shape)
} else {
background {
shape.fill(.thinMaterial)
}
.clipShape(shape)
}
}
}工作原理
让我们分析关键组件:
1. @ViewBuilder 属性
@ViewBuilder 属性允许函数根据 iOS 版本返回不同的视图类型。没有它,Swift 会要求两个分支返回相同的类型。
2. 可用性检查
if #available(iOS 26.0, *) {这个编译时检查确保 Liquid Glass 代码只在 iOS 26+ 上运行。编译器知道这是安全的,并允许在该分支中使用 .glassEffect() 修饰符。
3. 原生 Liquid Glass (iOS 26+)
self.glassEffect(interactive ? .regular.interactive() : .regular, in: shape)
.clipShape(shape)在 iOS 26+ 上,我们使用原生修饰符:
.regular变体用于标准玻璃外观.interactive()用于应该响应触摸并具有缩放和闪烁效果的控件- shape 参数控制玻璃边界
4. Material 降级 (iOS 18-25)
background {
shape.fill(.thinMaterial)
}
.clipShape(shape)对于旧版本,.thinMaterial 提供类似的半透明效果,与系统设计良好融合。
使用示例
带玻璃效果的基础按钮
Button("添加项目") {
// 操作
}
.padding()
.glassedEffect(in: Capsule())交互式浮动操作按钮
Button(action: 添加项目) {
HStack(spacing: 8) {
Image(systemName: "plus")
.font(.system(size: 20, weight: .semibold))
Text("添加级别")
}
.foregroundStyle(Color.primary)
.padding(.horizontal, 20)
.frame(height: 58)
.glassedEffect(in: Capsule(), interactive: true)
.shadow(color: Color.black.opacity(0.12), radius: 12, y: 8)
}圆角卡片
VStack(alignment: .leading) {
Text("统计数据")
.font(.headline)
Text("您的每周摘要")
.font(.subheadline)
.foregroundStyle(.secondary)
}
.padding()
.glassedEffect(in: RoundedRectangle(cornerRadius: 16))圆形图标按钮
Button(action: 显示设置) {
Image(systemName: "gear")
.font(.title2)
.frame(width: 44, height: 44)
.glassedEffect(in: Circle(), interactive: true)
}设计注意事项
何时使用玻璃效果
根据 Apple 的设计指南,Liquid Glass 应该保留用于导航层,而不是主要内容。考虑工具栏、浮动操作按钮和控制覆盖层。
避免嵌套玻璃
玻璃无法采样其他玻璃元素。如果你有多个相邻的玻璃元素,在 iOS 26+ 上将它们包装在 GlassEffectContainer 中以确保一致的视觉行为。
扩展更多选项
你可以扩展该扩展以支持更多玻璃变体:
extension View {
@ViewBuilder
func glassedEffect(
in shape: some Shape,
variant: GlassVariant = .regular,
interactive: Bool = false
) -> some View {
if #available(iOS 26.0, *) {
let glass: Glass = switch variant {
case .regular: .regular
case .clear: .clear
}
self.glassEffect(interactive ? glass.interactive() : glass, in: shape)
.clipShape(shape)
} else {
background {
shape.fill(.thinMaterial)
}
.clipShape(shape)
}
}
}
enum GlassVariant {
case regular
case clear
}总结
支持 iOS 26 的 Liquid Glass 同时保持向后兼容性不需要复杂的抽象。一个带有 @ViewBuilder 和 #available 检查的简单 View 扩展就能给你两全其美:新设备上的原生 Liquid Glass 和旧设备上优雅的 material 降级。
这种模式保持你的视图代码简洁——只需调用 .glassedEffect(in: Capsule()) 并让扩展处理其余部分。

