SwiftUI模态视图

6

如何从任何类或结构中以模态方式显示SwiftUI视图? 我使用UIKit中的UIHostingController。 有没有更好的方法仅使用SwiftUI来完成这项工作?

ContentView具有呈现SwiftUI视图的按钮

struct ContentView: View {
    var body: some View {
        Button {
            //  Present the view
            presentView(controller: UIHostingController(rootView: view))
        } label: {
            Text("Present view")
        }
    }
    
    var view: some View {
        Button {
            //  Dismiss the view
            dismissView()
        } label: {
            Rectangle()
                .overlay(
                    Text("Dismiss view")
                )
        }
    }
}

用于呈现SwiftUI视图的函数
extension ContentView {
    //  Returns the top view controller
    func topViewController() -> UIViewController? {
        let keyWindow = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
        if var topController = keyWindow?.rootViewController {
            while let presentedViewController = topController.presentedViewController { topController = presentedViewController }
            return topController
        } else { return nil }
    }
    
    //  Presents the SwiftUI view in a UIHostingController
    func presentView(controller: UIViewController) {
        controller.view.backgroundColor = .none
        controller.modalPresentationStyle = .overCurrentContext
        topViewController()?.present(controller, animated: false, completion: nil)
    }
    
    //  Removes the UIHostingViewController from root view
    func dismissView() {
        topViewController()?.dismiss(animated: false, completion: nil)
    }
}

我使用自定义通知来展示我的错误提示。该通知可以从任何地方发布,并在显示警报的视图模型中进行观察。 - lorem ipsum
1个回答

7
您可以像这样展示模态表单:
struct ContentView: View {
   @State private var showSheet = false

   var body: some View {
       Button("Present") { 
           showSheet.toggle() 
       }.font(.largeTitle)
       .sheet(isPresented: $showSheet) { 
           SheetView() 
       }
    }
}

struct SheetView: View {
   @Environment(\.dismiss) var dismiss

    var body: some View {
        ZStack {
           Button { 
              dismiss() 
           } label: {
               Image(systemName: "xmark.circle")
                 .font(.largeTitle)
                 .foregroundColor(.gray)
           }
         }
         .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
         .padding()
    }
}

或者像这样在全屏幕上呈现模态框:

struct ContentView: View {
   @State private var showSheet = false

   var body: some View {
       Button("Present") { 
          showSheet.toggle() 
       }.font(.largeTitle)
        .fullScreenCover(isPresented: $showSheet) {
              SheetView()
       }
   }
}
   
struct SheetView: View {
    @Environment(\.presentationMode) var presentationMode
 
     var body: some View {
    
         ZStack {
            Button { 
               presentationMode.wrappedValue.dismiss() 
             } label: {
                Image(systemName: "xmark.circle")
                .font(.largeTitle)
                .foregroundColor(.gray)
             }
       }
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing) 
        .padding()
   }
}

针对您的评论,没有问题,您只需这样做:

struct ContentView: View {
    @State private var showSheet = false

    var body: some View {
        ZStack {
            Button("Present") {
                showSheet.toggle()
            }
            .font(.largeTitle)
        
            if showSheet {
                ZStack {
                    Button {
                        showSheet.toggle()
                    } label: {
                        Image(systemName: "xmark.circle")
                            .font(.largeTitle)
                            .foregroundColor(.gray)
                    }
                    .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
                    .padding()
                }
                .background(.ultraThickMaterial)
            }
        }
    }
}

2
我喜欢它,但有没有办法以清晰的背景和无动画的方式在全屏上呈现模态框? - BPS
我已经添加到我的答案中了。希望你会觉得有用。 - Gal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接