SwiftUI:全屏覆盖的半透明背景



所以从技术上讲,我想显示一个加载屏幕视图。我正在使用fullScreenCover

struct ContentView: View {

@State private var isLoading = false

var body: some View {
VStack {
Text("Hello there")
Button("Start loading") {
isLoading.toggle()
}
.fullScreenCover(isPresented: $isLoading) {
ZStack{
Color.black.opacity(0.5).edgesIgnoringSafeArea(.all)
VStack {
ProgressView()
Button("Stop loading") {
isLoading.toggle()
}
}
}
}
}
}
}

问题是我无法使这个加载屏幕半透明。CCD_ 2或CCD_。

下面是一个可能方法的演示。您可以根据需要调整视觉效果的参数。

使用Xcode 12/iOS 14进行测试。

// ... other code
.fullScreenCover(isPresented: $isLoading) {
ZStack{
Color.black.opacity(0.5).edgesIgnoringSafeArea(.all)
VStack {
ProgressView()
Button("Stop loading") {
isLoading.toggle()
}
}
}
.background(BackgroundBlurView())
}
}
}
}
struct BackgroundBlurView: UIViewRepresentable {
func makeUIView(context: Context) -> UIView {
let view = UIVisualEffectView(effect: UIBlurEffect(style: .light))
DispatchQueue.main.async {
view.superview?.superview?.backgroundColor = .clear
}
return view
}
func updateUIView(_ uiView: UIView, context: Context) {}
}

f3dm76顶部的建筑答案:

我更改了它,这样后面的内容就不会闪烁(fullScreenCover后面加载的懒惰图像也发生了这种情况(。此外,我还想对全屏内容使用自定义转换(或者在某些情况下根本没有动画(,所以我也用这种方法删除了默认动画。

extension View {
func transparentNonAnimatingFullScreenCover<Content: View>(isPresented: Binding<Bool>, content: @escaping () -> Content) -> some View {
modifier(TransparentNonAnimatableFullScreenModifier(isPresented: isPresented, fullScreenContent: content))
}

}
private struct TransparentNonAnimatableFullScreenModifier<FullScreenContent: View>: ViewModifier {

@Binding var isPresented: Bool
let fullScreenContent: () -> (FullScreenContent)

func body(content: Content) -> some View {
content
.onChange(of: isPresented) { isPresented in
UIView.setAnimationsEnabled(false)
}
.fullScreenCover(isPresented: $isPresented,
content: {
ZStack {
fullScreenContent()
}
.background(FullScreenCoverBackgroundRemovalView())
.onAppear {
if !UIView.areAnimationsEnabled {
UIView.setAnimationsEnabled(true)
}
}
.onDisappear {
if !UIView.areAnimationsEnabled {
UIView.setAnimationsEnabled(true)
}
}
})
}

}
private struct FullScreenCoverBackgroundRemovalView: UIViewRepresentable {

private class BackgroundRemovalView: UIView {

override func didMoveToWindow() {
super.didMoveToWindow()

superview?.superview?.backgroundColor = .clear
}

}

func makeUIView(context: Context) -> UIView {
return BackgroundRemovalView()
}

func updateUIView(_ uiView: UIView, context: Context) {}

}

更新:请使用Povilas上面的答案来避免屏幕闪烁问题

Asperi的答案很漂亮,但如果您希望背景透明而不模糊,下面是您可以修改它的方法。为了方便起见,我还将代码移到了修饰符中。(xcode 13.3,iOS 15.4.1(

extension View {
func transparentFullScreenCover<Content: View>(isPresented: Binding<Bool>, content: @escaping () -> Content) -> some View {
fullScreenCover(isPresented: isPresented) {
ZStack {
content()
}
.background(TransparentBackground())
}
}
}
struct TransparentBackground: UIViewRepresentable {
func makeUIView(context: Context) -> UIView {
let view = UIView()
DispatchQueue.main.async {
view.superview?.superview?.backgroundColor = .clear
}
return view
}
func updateUIView(_ uiView: UIView, context: Context) {}
}

我发现了这种更干净的解决方案,可以解决清晰背景中的闪烁问题。

struct ClearBackgroundView: UIViewRepresentable {
func makeUIView(context: Context) -> UIView {
return InnerView()
}

func updateUIView(_ uiView: UIView, context: Context) {
}

private class InnerView: UIView {
override func didMoveToWindow() {
super.didMoveToWindow()

superview?.superview?.backgroundColor = .clear
}

}
}

使用

PresenterView()
.fullScreenCover(isPresented: $isPresented) {
PresentedView()
.background(ClearBackgroundView())
}

使用presentationBackground为模式(fullScreenCover、sheet、popover(设置所需的背景。来自文件:

允许演示文稿后面的视图通过半透明样式显示。

struct ContentView: View {

@State private var isLoading = false

var body: some View {
VStack {
Text("Hello there")
Button("Start loading") { isLoading.toggle() }
.fullScreenCover(isPresented: $isLoading) {
ZStack{
VStack {
ProgressView()
Button("Stop loading") { isLoading.toggle() }
}
}
.presentationBackground(black.opacity(0.5))
}
}
}
}

可用性

@available(iOS 16.4, macOS 13.3, tvOS 16.4, watchOS 9.4, *)

您也可以使用材料背景类型:

ZStack{
...
}
.background(.ultraThinMaterial)

有关更多用法,请参阅文档:https://developer.apple.com/documentation/swiftui/material

最新更新