[英]SwiftUI: Translucent background for fullScreenCover
所以從技術上講,我想顯示一個加載屏幕視圖。 我正在使用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()
}
}
}
}
}
}
}
問題是我不能使這個加載屏幕半透明。 sheet
或popover
的行為方式相同。
這是可能方式的演示。 您可以根據需要調整視覺效果參數。
使用 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) {}
}
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) {}
}
建立在 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) {}
}
您還可以使用 Material 背景類型:
ZStack{
...
}
.background(.ultraThinMaterial)
有關更多用法,請參閱文檔: https ://developer.apple.com/documentation/swiftui/material
我在清晰的背景中找到了針對閃爍問題的更清潔的解決方案。
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())
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.