有没有一种方法可以在 SwiftUI 中模糊背景?
Is there a method to blur a background in SwiftUI?
我想模糊视图的背景,但不想进入 UIKit 来完成它(例如 UIVisualEffectView
)我正在翻阅文档,但似乎一无所获无法实时剪辑背景并对其应用效果。是我错了还是看错了?
我还没有找到在 SwiftUI 中实现这一点的方法,但您可以通过 UIViewRepresentable
协议使用 UIKit 的东西。
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>) {
}
}
演示:
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")
}
}
}
}
}
我用 ZStack
在上面放了视图。
ZStack {
// List
ZStack {
// Blurred View
// Text
}
}
最后看起来像这样:
1。原生 SwiftUI 方式:
只需在需要模糊的任何内容上添加 .blur()
修饰符,例如:
Image("BG")
.blur(radius: 20)
注意视图的顶部和底部
请注意您可以Group
多个视图并将它们模糊在一起。
2。视觉效果视图:
你可以从 UIKit 中引入 prefect UIVisualEffectView
:
VisualEffectView(effect: UIBlurEffect(style: .dark))
有了这个小结构:
struct VisualEffectView: UIViewRepresentable {
var effect: UIVisualEffect?
func makeUIView(context: UIViewRepresentableContext<Self>) -> UIVisualEffectView { UIVisualEffectView() }
func updateUIView(_ uiView: UIVisualEffectView, context: UIViewRepresentableContext<Self>) { uiView.effect = effect }
}
3。 iOS15:材料
您可以通过一行代码使用iOS预定义材料:
.background(.ultraThinMaterial)
最简单的方法是 Richard Mullinix 的 here:
struct Blur: UIViewRepresentable {
var 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)
}
}
然后只需在您的代码中的某处使用它,例如背景:
//...
MyView()
.background(Blur(style: .systemUltraThinMaterial))
正如@mojtaba 所提到的,当您设置 resizable()
和 blur() 时,在图像顶部看到白色阴影是非常奇怪的。
一个简单的技巧是将图像填充提高到 -ve。
var body: some View {
return
ZStack {
Image("background_2").resizable()
.edgesIgnoringSafeArea(.all)
.blur(radius: 5)
.scaledToFill()
.padding(-20) //Trick: To escape from white patch @top & @bottom
}
}
结果:
@State private var amount: CGFLOAT = 0.0
var body: some View {
VStack{
Image("Car").resizable().blur(radius: amount, opaque: true)
}
}
使用“Opaque: true”和模糊功能将消除白噪声
有一个非常有用但不幸的是私人的(感谢Apple)class CABackdropLayer
它会复制下面的图层,我发现它在使用blend mode
或滤镜时很有用,它也可以用于模糊效果
代码
open class UIBackdropView: UIView {
open override class var layerClass: AnyClass {
NSClassFromString("CABackdropLayer") ?? CALayer.self
}
}
public struct Backdrop: UIViewRepresentable {
public init() {}
public func makeUIView(context: Context) -> UIBackdropView {
UIBackdropView()
}
public func updateUIView(_ uiView: UIBackdropView, context: Context) {}
}
public struct Blur: View {
public var radius: CGFloat
public var opaque: Bool
public init(radius: CGFloat = 3.0, opaque: Bool = false) {
self.radius = radius
self.opaque = opaque
}
public var body: some View {
Backdrop()
.blur(radius: radius, opaque: opaque)
}
}
用法
struct Example: View {
var body: some View {
ZStack {
YourBelowView()
YourTopView()
.background(Blur())
.background(Color.someColor.opacity(0.4))
}
}
}
Source
iOS 15 中的新增功能,SwiftUI
具有与 UIVisualEffectView
相当简单的等效项,它结合了 ZStack
、background()
修饰符和范围内置 materials.
ZStack {
Image("niceLook")
Text("Click me")
.padding()
.background(.thinMaterial)
}
您可以使用几种 material 类型中的一种来调整 material 的“厚度”——有多少背景内容可以透过。从最薄到最厚分别是:
.ultraThinMaterial
.thinMaterial
.regularMaterial
.thickMaterial
.ultraThickMaterial
Button("Test") {}
.background(Rectangle().fill(Color.red).blur(radius: 20))
我想模糊视图的背景,但不想进入 UIKit 来完成它(例如 UIVisualEffectView
)我正在翻阅文档,但似乎一无所获无法实时剪辑背景并对其应用效果。是我错了还是看错了?
我还没有找到在 SwiftUI 中实现这一点的方法,但您可以通过 UIViewRepresentable
协议使用 UIKit 的东西。
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>) {
}
}
演示:
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")
}
}
}
}
}
我用 ZStack
在上面放了视图。
ZStack {
// List
ZStack {
// Blurred View
// Text
}
}
最后看起来像这样:
1。原生 SwiftUI 方式:
只需在需要模糊的任何内容上添加 .blur()
修饰符,例如:
Image("BG")
.blur(radius: 20)
请注意您可以Group
多个视图并将它们模糊在一起。
2。视觉效果视图:
你可以从 UIKit 中引入 prefect UIVisualEffectView
:
VisualEffectView(effect: UIBlurEffect(style: .dark))
有了这个小结构:
struct VisualEffectView: UIViewRepresentable {
var effect: UIVisualEffect?
func makeUIView(context: UIViewRepresentableContext<Self>) -> UIVisualEffectView { UIVisualEffectView() }
func updateUIView(_ uiView: UIVisualEffectView, context: UIViewRepresentableContext<Self>) { uiView.effect = effect }
}
3。 iOS15:材料
您可以通过一行代码使用iOS预定义材料:
.background(.ultraThinMaterial)
最简单的方法是 Richard Mullinix 的 here:
struct Blur: UIViewRepresentable {
var 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)
}
}
然后只需在您的代码中的某处使用它,例如背景:
//...
MyView()
.background(Blur(style: .systemUltraThinMaterial))
正如@mojtaba 所提到的,当您设置 resizable()
和 blur() 时,在图像顶部看到白色阴影是非常奇怪的。
一个简单的技巧是将图像填充提高到 -ve。
var body: some View {
return
ZStack {
Image("background_2").resizable()
.edgesIgnoringSafeArea(.all)
.blur(radius: 5)
.scaledToFill()
.padding(-20) //Trick: To escape from white patch @top & @bottom
}
}
结果:
@State private var amount: CGFLOAT = 0.0
var body: some View {
VStack{
Image("Car").resizable().blur(radius: amount, opaque: true)
}
}
使用“Opaque: true”和模糊功能将消除白噪声
有一个非常有用但不幸的是私人的(感谢Apple)class CABackdropLayer
它会复制下面的图层,我发现它在使用blend mode
或滤镜时很有用,它也可以用于模糊效果
代码
open class UIBackdropView: UIView {
open override class var layerClass: AnyClass {
NSClassFromString("CABackdropLayer") ?? CALayer.self
}
}
public struct Backdrop: UIViewRepresentable {
public init() {}
public func makeUIView(context: Context) -> UIBackdropView {
UIBackdropView()
}
public func updateUIView(_ uiView: UIBackdropView, context: Context) {}
}
public struct Blur: View {
public var radius: CGFloat
public var opaque: Bool
public init(radius: CGFloat = 3.0, opaque: Bool = false) {
self.radius = radius
self.opaque = opaque
}
public var body: some View {
Backdrop()
.blur(radius: radius, opaque: opaque)
}
}
用法
struct Example: View {
var body: some View {
ZStack {
YourBelowView()
YourTopView()
.background(Blur())
.background(Color.someColor.opacity(0.4))
}
}
}
Source
iOS 15 中的新增功能,SwiftUI
具有与 UIVisualEffectView
相当简单的等效项,它结合了 ZStack
、background()
修饰符和范围内置 materials.
ZStack {
Image("niceLook")
Text("Click me")
.padding()
.background(.thinMaterial)
}
您可以使用几种 material 类型中的一种来调整 material 的“厚度”——有多少背景内容可以透过。从最薄到最厚分别是:
.ultraThinMaterial
.thinMaterial
.regularMaterial
.thickMaterial
.ultraThickMaterial
Button("Test") {}
.background(Rectangle().fill(Color.red).blur(radius: 20))