模糊效果(Blur Effect)是 iOS 用户界面设计的重要组成部分,它被广泛应用于系统控制中心、通知背景、弹窗蒙版等场景,营造出“毛玻璃”的视觉层次感。
本文将深入解析 SwiftUI 中实现模糊效果的三种主流方式:.blur(radius:)
、.background(Material)
、以及封装 UIKit 的 UIVisualEffectView
,并详细说明每种方式的适用场景、性能表现及实现方式。
一、使用 .blur(radius:)
修饰符添加模糊
基础用法
Image("photo").resizable().scaledToFill().blur(radius: 10)
API 说明
- 函数名:
.blur(radius:opaque:)
- 参数:
radius: CGFloat
:模糊的半径,数值越大,模糊越强;opaque: Bool = false
(可选):- 设置为
true
会提升性能,但会关闭透明效果; - 设置为
false
可以保留透明度,适用于图像叠加。
- 设置为
示例:模糊前景图像
ZStack {Image("background").resizable().scaledToFill()Image("logo").resizable().frame(width: 100, height: 100).blur(radius: 8)
}
✅ 适合前景局部模糊,⚠️ 不具备“磨砂玻璃”风格的半透明模糊。
二、使用系统材料 Material
实现半透明磨砂效果
从 iOS 15 起,Apple 为 SwiftUI 引入了 视觉材料 API(Material API),用于模拟 iOS 系统的磨砂玻璃风格(例如通知中心、弹窗等)。
基础用法
Text("Hello, SwiftUI").padding().background(.ultraThinMaterial).cornerRadius(12)
API 说明
@inlinable nonisolated public func background<S>(_ style: S, ignoresSafeAreaEdges edges: Edge.Set = .all) -> some View where S : ShapeStyle
Material
类型
@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 10.0, *)
extension ShapeStyle where Self == Material {/// A material that's somewhat translucent.public static var regularMaterial: Material { get }/// A material that's more opaque than translucent.public static var thickMaterial: Material { get }/// A material that's more translucent than opaque.public static var thinMaterial: Material { get }/// A mostly translucent material.public static var ultraThinMaterial: Material { get }/// A mostly opaque material.public static var ultraThickMaterial: Material { get }
}
.ultraThinMaterial
:最透明的视觉效果;.thinMaterial
:比 ultraThin 稍微厚一点;.regularMaterial
:中等模糊;.thickMaterial
:模糊感更强;.ultraThickMaterial
:非常明显的模糊层。
示例:毛玻璃背景卡片
ZStack {Image("background").resizable().scaledToFill().ignoresSafeArea()VStack {Text("This is a glass card").font(.headline).foregroundColor(.white).padding().background(.ultraThinMaterial).cornerRadius(16)}
}
优势
- 系统原生优化;
- 自动根据暗黑/亮色模式适配背景;
- 可叠加阴影、边框等样式。
三、封装 UIKit 的 UIVisualEffectView
用于自定义模糊风格
在 SwiftUI 中,若需要更细致的控制,比如使用 .dark
、.extraLight
等传统 UIKit 风格的模糊效果,可通过 UIViewRepresentable
封装 UIKit 的 UIVisualEffectView
。
Step 1:创建封装视图组件
struct VisualEffectBlur: UIViewRepresentable {var blurStyle: UIBlurEffect.Stylefunc makeUIView(context: Context) -> UIVisualEffectView {return UIVisualEffectView(effect: UIBlurEffect(style: blurStyle))}func updateUIView(_ uiView: UIVisualEffectView, context: Context) {uiView.effect = UIBlurEffect(style: blurStyle)}
}
UIBlurEffect.Style 枚举(UIKit)
extension UIBlurEffect {@available(iOS 8.0, *)public enum Style : Int, @unchecked Sendable {/// 非常浅的白色模糊(适合深色背景)case extraLight = 0/// 淡白色模糊,透明度适中(适合中性色背景)case light = 1/// 深色模糊,带有黑色背景(适合浅色背景或亮色 UI)case dark = 2/// 常规模糊效果,视觉强度适中,适用于大部分场景@available(iOS 10.0, *)case regular = 4/// 强烈的模糊效果,比 regular 更加明显@available(iOS 10.0, *)case prominent = 5// MARK: - 以下为基于系统材质的模糊效果,自动适配明/暗模式/// 极薄系统材料风格,模糊度最轻(自适应明暗模式)@available(iOS 13.0, *)case systemUltraThinMaterial = 6/// 较薄系统材料风格(比 ultraThin 稍强)@available(iOS 13.0, *)case systemThinMaterial = 7/// 常规厚度系统材料,适用于大多数模糊背景@available(iOS 13.0, *)case systemMaterial = 8/// 较厚系统材料模糊,遮挡性更强@available(iOS 13.0, *)case systemThickMaterial = 9/// 特别为 toolbar、tabbar 等 chrome UI 元素设计的材料模糊@available(iOS 13.0, *)case systemChromeMaterial = 10// MARK: - 以下为固定亮色风格的材料模糊(不会根据暗色模式变换)/// 极薄亮色材料@available(iOS 13.0, *)case systemUltraThinMaterialLight = 11/// 较薄亮色材料@available(iOS 13.0, *)case systemThinMaterialLight = 12/// 常规亮色材料@available(iOS 13.0, *)case systemMaterialLight = 13/// 厚重亮色材料@available(iOS 13.0, *)case systemThickMaterialLight = 14/// 用于亮色 UI chrome 元素的材料@available(iOS 13.0, *)case systemChromeMaterialLight = 15// MARK: - 以下为固定暗色风格的材料模糊(不会根据亮色模式变换)/// 极薄暗色材料@available(iOS 13.0, *)case systemUltraThinMaterialDark = 16/// 较薄暗色材料@available(iOS 13.0, *)case systemThinMaterialDark = 17/// 常规暗色材料@available(iOS 13.0, *)case systemMaterialDark = 18/// 厚重暗色材料@available(iOS 13.0, *)case systemThickMaterialDark = 19/// 用于暗色 UI chrome 元素的材料@available(iOS 13.0, *)case systemChromeMaterialDark = 20}
}
Step 2:在 SwiftUI 中使用
// 枚举所有 UIBlurEffect.Style(仅支持当前系统版本的)let blurStyles: [(name: String, style: UIBlurEffect.Style)] = [("extraLight", .extraLight),("light", .light),("dark", .dark),("regular", .regular),("prominent", .prominent),("systemUltraThinMaterial", .systemUltraThinMaterial),("systemThinMaterial", .systemThinMaterial),("systemMaterial", .systemMaterial),("systemThickMaterial", .systemThickMaterial),("systemChromeMaterial", .systemChromeMaterial),("systemUltraThinMaterialLight", .systemUltraThinMaterialLight),("systemThinMaterialLight", .systemThinMaterialLight),("systemMaterialLight", .systemMaterialLight),("systemThickMaterialLight", .systemThickMaterialLight),("systemChromeMaterialLight", .systemChromeMaterialLight),("systemUltraThinMaterialDark", .systemUltraThinMaterialDark),("systemThinMaterialDark", .systemThinMaterialDark),("systemMaterialDark", .systemMaterialDark),("systemThickMaterialDark", .systemThickMaterialDark),("systemChromeMaterialDark", .systemChromeMaterialDark),]var body: some View {ScrollView {VStack(spacing: 0) {ForEach(blurStyles, id: \.name) { item inZStack {Image("background").resizable().scaledToFill().frame(height: 150).clipped()VisualEffectBlur(blurStyle: item.style).frame(height: 150)Text(item.name).font(.title3).bold().foregroundColor(.white).shadow(radius: 2)}.frame(maxWidth: .infinity)}}}}
}
实战技巧:只模糊部分区域
示例:只模糊圆形区域
ZStack {Image("background").resizable().scaledToFill()Circle().fill(.thinMaterial).frame(width: 180, height: 180)
}
示例:自定义模糊背景加遮罩
VisualEffectBlur(blurStyle: .light).mask(RoundedRectangle(cornerRadius: 20).frame(width: 300, height: 200))
性能注意事项
技术 | 系统要求 | 性能表现 | 使用建议 |
---|---|---|---|
.blur(radius:) | iOS 13+ | 渲染开销较高 | 少量、静态使用 |
.background(.material) | iOS 15+ | 系统优化 | 推荐优先使用 |
UIVisualEffectView 封装 | iOS 13+ | 原生高效 | 可用于旧版本 |
建议避免在 滚动视图或动画 中频繁使用大半径的 .blur(radius:)
,可以改用 Material
实现近似视觉风格但更高性能。
附加内容:模糊叠加 + 动画
struct AnimatedBlurView: View {@State private var blurAmount: CGFloat = 0var body: some View {VStack {Image("background").resizable().scaledToFill().frame(height: 300).blur(radius: blurAmount)Text("blur value: \(blurAmount)")Slider(value: $blurAmount, in: 0...20).padding()}}
}
总结
模糊方式 | 系统支持 | 适用场景 | 控制精度 |
---|---|---|---|
.blur(radius:) | iOS 13+ | 简单模糊、图片处理 | 高(可动画) |
.background(.material) | iOS 15+ | 毛玻璃视觉、系统一致性 | 中 |
UIVisualEffectView | iOS 13+ | 自定义模糊、旧系统支持 | 高 |
SwiftUI 通过系统级 API 与 UIKit 封装的配合,已能满足多数现代 iOS UI 设计中关于模糊效果的需求。选择合适的模糊方式,不仅能提升用户体验,还能确保性能表现优良。
最后,希望能够帮助到有需要的朋友,如果觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。
📚 推荐阅读
- Apple Developer - Material
- WWDC2021: Explore visual effects in SwiftUI
- UIVisualEffectView | Apple Documentation