【发布时间】:2019-10-29 20:18:09
【问题描述】:
我希望模糊视图的背景,但不想闯入 UIKit 来完成它(例如 UIVisualEffectView)我正在挖掘文档但一无所获,似乎没有办法实时剪辑背景并对其应用效果。是我错了还是调查方式不对?
【问题讨论】:
我希望模糊视图的背景,但不想闯入 UIKit 来完成它(例如 UIVisualEffectView)我正在挖掘文档但一无所获,似乎没有办法实时剪辑背景并对其应用效果。是我错了还是调查方式不对?
【问题讨论】:
只需在需要模糊的任何内容上添加.blur() 修饰符:
Image("BG")
.blur(radius: 20)
请注意您可以Group多个视图并将它们模糊在一起。
您可以从 UIKit 中带上级长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 }
}
一行代码即可使用iOS预定义素材:
.background(.ultraThinMaterial)
【讨论】:
我还没有找到在 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
}
}
最终看起来像这样:
【讨论】:
最简单的方法是 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))
【讨论】:
【讨论】:
.blur 修饰符添加另一个参数。如果你使用.blur(radius: 5, opaque: true),它应该去掉那个白色阴影。
@State private var amount: CGFLOAT = 0.0
var body: some View {
VStack{
Image("Car").resizable().blur(radius: amount, opaque: true)
}
}
使用带有模糊功能的“Opaque: true”将消除白噪声
【讨论】:
iOS 15 中的新功能,SwiftUI 与 UIVisualEffectView 非常简单等效,它结合了 ZStack、background() 修饰符和一系列内置材料。
ZStack {
Image("niceLook")
Text("Click me")
.padding()
.background(.thinMaterial)
}
您可以使用多种材质类型中的一种来调整材质的“厚度”——背景内容的透光程度。从最薄到最厚,分别是:
.ultraThinMaterial
.thinMaterial
.regularMaterial
.thickMaterial
.ultraThickMaterial
【讨论】:
有一个非常有用但不幸的是私人(感谢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))
}
}
}
【讨论】: