swift 如何在工作表视图中使用不透明的背景色?

wsewodh2  于 5个月前  发布在  Swift
关注(0)|答案(8)|浏览(56)

我正在使用SwiftUI开发一个应用程序。
我正在寻找一些方法,使一个不透明的工作表视图的背景颜色。
有什么办法吗?
我试着用下面的代码做到这一点,我可以用不透明度属性更改颜色,但我看不到工作表视图下的文本(工作表)。

import SwiftUI

struct ContentView: View {
    
    @State var isSheet = false
    
    var body: some View {
       
        Button(action: {self.isSheet.toggle()}) {
            Text("Sheet")
        }.sheet(isPresented: $isSheet){
            Color.yellow.opacity(0.5)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

字符串
Xcode:Version 11.7
Swift:Swift 5

vvppvyoh

vvppvyoh1#

你不能使用标准的工作表官方API(因为默认情况下每个主机控制器视图都是不透明的),所以你可以创建自定义工作表视图(带有你需要的任何功能),或者使用运行时解决方法来找到该视图并将其背景设置为清除。


的数据

struct DemoView: View {

    @State var isSheet = false

    var body: some View {

        Button(action: {self.isSheet.toggle()}) {
            Text("Sheet")
        }.sheet(isPresented: $isSheet){
            Color.yellow.opacity(0.5)
                .background(BackgroundClearView())
        }
    }
}

struct BackgroundClearView: 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) {}
}

字符串
backup

7y4bm7vi

7y4bm7vi2#

使用我一整天都在努力寻找的来自@ marti的令人敬畏的答案,我已经构建了一个简单的视图修改器,现在可以在.sheet或.fullScreenCover模态视图中应用,并提供透明的背景。然后您可以根据需要为内容设置框架修改器,以适应屏幕,而无需用户知道模态不是自定义大小。

import SwiftUI

struct ClearBackgroundView: UIViewRepresentable {
    func makeUIView(context: Context) -> some UIView {
        let view = UIView()
        DispatchQueue.main.async {
            view.superview?.superview?.backgroundColor = .clear
        }
        return view
    }
    func updateUIView(_ uiView: UIViewType, context: Context) {
    }
}

struct ClearBackgroundViewModifier: ViewModifier {
    
    func body(content: Content) -> some View {
        content
            .background(ClearBackgroundView())
    }
}

extension View {
    func clearModalBackground()->some View {
        self.modifier(ClearBackgroundViewModifier())
    }
}

字符串
使用方法:

.sheet(isPresented: $isPresented) {
            ContentToDisplay()
            .frame(width: 300, height: 400)
            .clearModalBackground()
    }

pkbketx9

pkbketx93#

从iOS 16.4开始,应该可以使用带有颜色和模糊的.presentationBackground(_ style: S)material types)。如果你想为一张纸制作透明背景:

struct ContentView: View {    
    @State private var isPresented = false
    var body: some View {
        Button(action: {
            isPresented.toggle()
        }, label: {
            Label("Sheet", systemImage: "list.bullet.rectangle.portrait")
        })
        .sheet(isPresented: $isPresented) {
            Text("Detail")
                .presentationBackground(.clear)
        }
    }
}

字符串
或者你可以使用.presentationBackground()来继承presenter的背景样式。

struct ContentView: View {
    @State private var isPresented = false
    var body: some View {
        Button(action: {
            isPresented.toggle()
        }, label: {
            Label("Sheet", systemImage: "list.bullet.rectangle.portrait")
        })
        .sheet(isPresented: $isPresented) {
            Text("Detail")
                .presentationBackground()
        }
        .backgroundStyle(Color("myThemeBackground"))
    }
}

b09cbbtk

b09cbbtk4#

虽然提供的解决方案确实有效,但当它们被交换时,它们也会保持背景对 * 其他 * 工作表透明。
所以需要在dismantleUIView中恢复背景颜色,如下所示:

struct TransparentBackground: UIViewRepresentable {
    @MainActor
    private static var backgroundColor: UIColor?

    func makeUIView(context: Context) -> UIView {
        let view = UIView()
        Task {
            Self.backgroundColor = view.superview?.superview?.backgroundColor
            view.superview?.superview?.backgroundColor = .clear
        }
        return view
    }

    static func dismantleUIView(_ uiView: UIView, coordinator: ()) {
        uiView.superview?.superview?.backgroundColor = Self.backgroundColor
    }

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

字符串
请注意,我使用了Swift中新的并发特性。

mrzz3bfm

mrzz3bfm5#

对于那些认为依赖于DispatchQueue中的消息顺序不是一个好主意的人(实际上不是),这里有一个依赖于重写didMoveToSuperview()的解决方案。
这仍然不是100%的未来证明,因为我们正在修改superview的superview,并且不能保证它在我们自己的视图添加到层次结构时可用,但我认为这仍然比DispatchQueue解决方案更好,因为视图通常是从上到下添加的,即当调用didMoveToSuperview()时,superview的superview可能可用。

struct DemoView: View {

    @State var isSheet = false

    var body: some View {

        Button(action: {self.isSheet.toggle()}) {
            Text("Sheet")
        }.sheet(isPresented: $isSheet){
            Color.yellow.opacity(0.5)
                .background(BackgroundClearView())
        }
    }
}

struct BackgroundClearView: UIViewRepresentable {

    private class View: UIView {
        override func didMoveToSuperview() {
            super.didMoveToSuperview()
            superview?.superview?.backgroundColor = .clear
        }
    }

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

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

字符串

scyqe7ek

scyqe7ek6#

把它放在Modal.swift中:

import SwiftUI

// View modifiers for modals: .sheet, .fullScreenCover

struct ModalColorView: UIViewRepresentable {
    
    let color: UIColor
    
    func makeUIView(context: Context) -> some UIView {
        let view = UIView()
        DispatchQueue.main.async {
            view.superview?.superview?.backgroundColor = color
        }
        return view
    }
    
    func updateUIView(_ uiView: UIViewType, context: Context) {}
}

struct ModalColorViewModifier: ViewModifier {
    
    let color: UIColor
    
    func body(content: Content) -> some View {
        content
            .background(ModalColorView(color: color))
    }
}

extension View {
    /// Set transparent or custom color for a modal background (.screen, .fullScreenCover)
    func modalColor(_ color: UIColor = .clear) -> some View {
        self.modifier(ModalColorViewModifier(color: color))
    }
}

字符串
像这样使用:

.sheet(isPresented: $show) {
  YourModalView(isPresented: $show)
    // Zero args default is transparent (.clear)
    //.modalColor()
    // ..or specify a UIColor of choice.
    .modalColor(UIColor(white: 0.2, alpha: 0.3))
  }
}

kkih6yb8

kkih6yb87#

阿森伯格不希望他的答案被编辑,所以单独发布:

struct ContentView: View {

    @SwiftUI.State var showSheet = false
    @SwiftUI.State var appear: Bool = false
    
    var body: some View {

        Button(action: {self. showSheet.toggle()}) {
            Text("Sheet")
        }.sheet(isPresented: $showSheet){
            Color.blue.opacity(0.5)
            .background(ClearBackgroundView(appear: $appear))
            .onAppear {DispatchQueue.main.async {appear = true}}
        }
    }
}

struct ClearBackgroundView: UIViewRepresentable {

    @Binding var appear: Bool

    class ClearView: UIView {
        override func didMoveToSuperview() {
            super.didMoveToSuperview()
            clearBackgroundColor()
        }

        func clearBackgroundColor() {
            var view: UIView? = self.superview?.superview
            while let subview = view {
                subview.backgroundColor = .clear
                view = subview.superview
            }
        }
    }

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

    func updateUIView(_ uiView: ClearView, context: Context) {
        uiView.clearBackgroundColor()
    }
}

字符串

amrnrhlw

amrnrhlw8#

在SwiftUI中,sheet修饰符通常用于呈现新视图,而不是样式化背景。要实现所需的不透明度背景颜色,您可以使用ZStack和Color视图的组合。下面是一个示例:

import SwiftUI

struct ContentView: View {
    
    @State private var isSheetPresented = false
    
    var body: some View {
        ZStack {
            Button(action: { self.isSheetPresented.toggle() }) {
                Text("Sheet")
            }
            
            if isSheetPresented {
                Color.yellow.opacity(0.5)
                    .edgesIgnoringSafeArea(.all)
                    .onTapGesture {
                        self.isSheetPresented.toggle()
                    }
                
                // Your sheet content goes here
                VStack {
                    Text("Sheet Content")
                        .foregroundColor(.white)
                    // Add more content as needed
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

字符串
在这个例子中,使用ZStack来覆盖按钮和背景颜色。当点击按钮时,会显示具有所需背景颜色和不透明度的Color视图,覆盖整个屏幕。您可以自定义VStack内部的内容,以显示所需的工作表内容。
另外,请注意在背景颜色上使用onTapGesture来在点击时关闭工作表。根据应用程序的设计调整颜色,不透明度和内容。

相关问题