SwiftUI 中的模糊效果详解:.blur、.material、UIVisualEffectView_uiblureffect.style
模糊效果(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.Style func 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 in ZStack { 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:)
.background(.material)
UIVisualEffectView
封装建议避免在 滚动视图或动画 中频繁使用大半径的 .blur(radius:)
,可以改用 Material
实现近似视觉风格但更高性能。
附加内容:模糊叠加 + 动画
struct AnimatedBlurView: View { @State private var blurAmount: CGFloat = 0 var 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:)
.background(.material)
UIVisualEffectView
SwiftUI 通过系统级 API 与 UIKit 封装的配合,已能满足多数现代 iOS UI 设计中关于模糊效果的需求。选择合适的模糊方式,不仅能提升用户体验,还能确保性能表现优良。
最后,希望能够帮助到有需要的朋友,如果觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。
📚 推荐阅读
- Apple Developer - Material
- WWDC2021: Explore visual effects in SwiftUI
- UIVisualEffectView | Apple Documentation