I'm looking to blur a view's background but don't want to have to break out into UIKit to accomplish it (eg. a UIVisualEffectView
) I'm digging through docs and got nowhere, seemingly there is no way to live-clip a background and apply effects to it. Am I wrong or looking into it the wrong way?
可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
回答1:
I haven't found a way to achieve that in SwiftUI yet, but you can use UIKit stuff via UIViewRepresentable
protocol.
struct BlurView: UIViewRepresentable {
let style: UIBlurEffect.Style
func makeUIView(context: UIViewRepresentableContext<BlurView>) -> UIView {
let view = UIView(frame: .zero)
view.backgroundColor = .clear
let blurEffect = UIBlurEffect(style: style)
let blurView = UIVisualEffectView(effect: blurEffect)
blurView.translatesAutoresizingMaskIntoConstraints = false
view.insertSubview(blurView, at: 0)
NSLayoutConstraint.activate([
blurView.heightAnchor.constraint(equalTo: view.heightAnchor),
blurView.widthAnchor.constraint(equalTo: view.widthAnchor),
])
return view
}
func updateUIView(_ uiView: UIView,
context: UIViewRepresentableContext<BlurView>) {
}
}
Demo:
struct ContentView: View {
var body: some View {
NavigationView {
ZStack {
List(1...100) { item in
Rectangle().foregroundColor(Color.pink)
}
.navigationBarTitle(Text("A List"))
ZStack {
BlurView(style: .light)
.frame(width: 300, height: 300)
Text("Hey there, I'm on top of the blur")
}
}
}
}
}
I used ZStack
to put views on top of it.
ZStack {
// List
ZStack {
// Blurred View
// Text
}
}
And ends up looking like this:
回答2:
The Native SwiftUI way:
You can add .blur()
modifier on anything you need to be blurry like:
struct ContentView: View {
var body: some View {
ZStack {
Image("BG")
.resizable()
.scaledToFill()
.edgesIgnoringSafeArea(.all)
.blur(radius: 20) // <- this is the important modifier. The rest is just for demo
Text("Hello \nSwiftUI Blur Effect")
.font(.largeTitle)
.fontWeight(.black)
.foregroundColor(.white)
}
}
}
Note the top and bottom of the view
Note that you can Group
multiple views and blur them together.
The Visual Effect View:
You can define a VisualEffectView
with just 5 lines of code:
struct VisualEffectView: UIViewRepresentable {
var effect: UIVisualEffect?
func makeUIView(context: UIViewRepresentableContext<Self>) -> UIVisualEffectView { UIVisualEffectView() }
func updateUIView(_ uiView: UIVisualEffectView, context: UIViewRepresentableContext<Self>) { uiView.effect = effect }
}
Usage Example:
struct ContentView: View {
var body: some View {
ZStack {
Image("BG")
.resizable()
.scaledToFill()
.edgesIgnoringSafeArea(.all)
VisualEffectView(effect: UIBlurEffect(style: .dark))
.edgesIgnoringSafeArea(.all)
Text("Hello \nVisual Effect View")
.font(.largeTitle)
.fontWeight(.black)
.foregroundColor(.white)
}
}
}
回答3:
The simplest way is here by Richard Mullinix:
struct Blur: UIViewRepresentable {
let style: UIBlurEffect.Style = .systemMaterial
func makeUIView(context: Context) -> UIVisualEffectView {
return UIVisualEffectView(effect: UIBlurEffect(style: style))
}
func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
uiView.effect = UIBlurEffect(style: style)
}
}
Then just use it somewhere in your code like background:
//...
MyView()
.background(Blur(style: .systemUltraThinMaterial))