我希望模糊视图的背景,但是不想闯入UIKit来完成它(例如UIVisualEffectView
)。我正在浏览文档,却一无所获,看来那里无法实时剪辑背景并对其应用效果。我是错还是以错误的方式调查它?
答案 0 :(得分:13)
最简单的方法是Richard Mullinix的here:
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)
}
}
然后仅在代码中使用它的某个位置,例如背景:
//...
MyView()
.background(Blur(style: .systemUltraThinMaterial))
答案 1 :(得分:4)
您可以在任何需要模糊的地方添加.blur()
修饰符,例如:
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)
}
}
}
请注意,您可以Group
多个视图并将它们模糊在一起。
您可以仅用5行代码来定义VisualEffectView
:
struct VisualEffectView: UIViewRepresentable {
var effect: UIVisualEffect?
func makeUIView(context: UIViewRepresentableContext<Self>) -> UIVisualEffectView { UIVisualEffectView() }
func updateUIView(_ uiView: UIVisualEffectView, context: UIViewRepresentableContext<Self>) { uiView.effect = effect }
}
用法示例:
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)
}
}
}
答案 2 :(得分:3)
我还没有找到在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
}
}
最终看起来像这样:
答案 3 :(得分:1)
如@mojtaba所述,在将resizable()
和blur()一起设置时,在图像顶部看到白色阴影是非常奇怪的。
一个简单的技巧就是将Image填充提高到-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
}
}
答案 4 :(得分:1)
iOS 15 中的新功能,SwiftUI
具有与 UIVisualEffectView
非常简单的等效项,它结合了 ZStack
、background()
修饰符和一系列内置材料。
ZStack {
Image("niceLook")
Text("Click me")
.padding()
.background(.thinMaterial)
}
您可以通过使用多种材料类型之一来调整材料的“厚度”——背景内容的透光程度。从最薄到最厚,它们是:
.ultraThinMaterial
.thinMaterial
.regularMaterial
.thickMaterial
.ultraThickMaterial
答案 5 :(得分:0)
@State private var amount: CGFLOAT = 0.0
var body: some View {
VStack{
Image("Car").resizable().blur(radius: amount, opaque: true)
}
}
使用具有模糊功能的“不透明:真”将消除白噪声
答案 6 :(得分:-1)
有一个非常有用但不幸的是私有(感谢 Apple)类 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))
}
}
}