SwiftUI 2.0如何给视图添加带镂空遮罩的模糊效果且不使用UIViewRepresentable
SwiftUI 2.0(iOS14+)纯原生实现带镂空的新手引导模糊蒙层方案
可以实现,完全不需要借助UIViewRepresentable,仅用SwiftUI 2.0原生API即可完成,最低兼容iOS14,且支持全局复用,不需要拆分原有视图层级里的高亮元素。
实现核心逻辑
利用blur()修饰符+mask()反向路径裁剪的组合,让模糊效果和半透明蒙层仅作用在非镂空区域,镂空位置直接透出下层未经处理的原始视图,自然不会被模糊或蒙层覆盖。
完整代码实现
1. 可复用的新手引导修饰符
import SwiftUI // 新手引导蒙层修饰符 struct CoachMarkModifier: ViewModifier { // 镂空区域的frame(全局坐标系) let hollowRect: CGRect // 模糊半径 let blurRadius: CGFloat = 5 // 半透蒙层透明度 let maskOpacity: Double = 0.3 // 镂空区域圆角 let hollowCornerRadius: CGFloat = 8 func body(content: Content) -> some View { content .overlay( // 模糊层+蒙层组合 content .blur(radius: blurRadius) .overlay( Color.black.opacity(maskOpacity) ) // 反向裁剪,挖掉镂空区域 .mask( Path { path in path.addRect(UIScreen.main.bounds) path.addRoundedRect(in: hollowRect, cornerSize: .init(width: hollowCornerRadius, height: hollowCornerRadius)) } .fill(style: .init(eoFill: true)) ) ) } } // 扩展View简化调用 extension View { func addCoachMark(hollowRect: CGRect) -> some View { self.modifier(CoachMarkModifier(hollowRect: hollowRect)) } }
2. 无侵入获取高亮元素坐标(不需要拆分原视图)
通过PreferenceKey获取需要高亮的元素的全局坐标,不需要修改原有视图层级:
// 用于获取视图frame的PreferenceKey struct HollowRectPreferenceKey: PreferenceKey { static var defaultValue: CGRect = .zero static func reduce(value: inout CGRect, nextValue: () -> CGRect) { value = nextValue() } }
3. 使用示例
struct DemoView: View { @State private var hollowRect: CGRect = .zero var body: some View { VStack(spacing: 30) { // 原有层级内的高亮元素,无需拆分 Image(systemName: "flag") .font(.system(size: 40)) .foregroundColor(.red) // 仅需加一行修饰符获取自身全局坐标 .background( GeometryReader { geo in Color.clear .preference(key: HollowRectPreferenceKey.self, value: geo.frame(in: .global)) } ) Text("其他页面内容") Button("普通操作按钮") {} } // 接收高亮元素的坐标 .onPreferenceChange(HollowRectPreferenceKey.self, perform: { value in hollowRect = value }) // 挂载新手引导效果 .addCoachMark(hollowRect: hollowRect) } }
扩展说明
- 如需支持多个镂空区域,只需在mask的Path内多次添加挖空路径即可
- 支持圆形、异形等任意形状的镂空,仅需修改Path的生成逻辑
- 完全不侵入原有视图层级,全局复用性符合需求
内容的提问来源于stack exchange,提问作者I. Pedan
相关产品推荐
相关产品推荐

