模糊效果(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