简体   繁体   English

SwiftUI - 如何关闭假模态视图 - 从里面的第二个视图,带有关闭按钮?

[英]SwiftUI - How to close a fake Modal View - from the second view inside it, with a close button?

I have a tricky design.我有一个棘手的设计。 I'm trying to have a close button that from whatever views, inside a "fake" Modal View (fake cause it's full screen, thanks to a code that i found online), it's gonna close the Modal View.我试图有一个关闭按钮,从任何视图中,在“假”模态视图中(假因为它是全屏的,多亏了我在网上找到的代码),它将关闭模态视图。 Right now the close button is working in the first view that open in the modal view, but I need it to work also in the next views of the modal view, cause I have a flow inside this modal view to create an item.现在关闭按钮在模态视图中打开的第一个视图中工作,但我需要它在模态视图的下一个视图中也能工作,因为我在这个模态视图中有一个流程来创建一个项目。

This is the View from which I start ColorNewItemView, my fake Modal View.这是我启动 ColorNewItemView 的视图,我的假模态视图。

struct RecapItemToAdd: View {

  @State var isPresented: Bool = false

    var body: some View {
      NavigationView {
        
        VStack {
            
            Button(action: { withAnimation { self.isPresented.toggle()}}) {
            Image(systemName: "pencil")
                .resizable()
                .renderingMode(.original)
                .frame(width: 13, height: 17)
                .foregroundColor(UIManager.hLightGrey)
            }

        }
        
        ZStack {
             VStack(alignment: .leading) {
                 ColorNewItemView(isPresenteded: self.$isPresented)

                 Spacer()
               }


         }
         .background(Color.white)
         .edgesIgnoringSafeArea(.all)
         .offset(x: 0, y: self.isPresented ? 0 : UIApplication.shared.keyWindow?.frame.height ?? 0)
    }

   }
 
}

Note: I know that "keyWindow" is deprecated but I don't know how to change it.注意:我知道“keyWindow”已被弃用,但我不知道如何更改它。

With ColorNewItemView starts my full screen Modal View.使用 ColorNewItemView 启动我的全屏模式视图。 In this view the close button works.在此视图中,关闭按钮有效。

   struct ColorNewItemView: View {

   @State var selection: Int? = nil

   @Binding var isPresenteded: Bool

      var body: some View {
      NavigationStackView {
         VStack(alignment: .center) {

          Button(action: {
                  self.isPresenteded = false
              }) {
                  Image(systemName: "xmark.circle.fill")
                  .resizable()
                  .frame(width: 30, height: 30)
                  .foregroundColor(UIManager.hBlueLight)
              }
    
    Text("First View")
            .font(UIManager.einaTitle)
            .foregroundColor(UIManager.hDarkBlue)
    
    
    Image("black-hoodie")
    .resizable()
    .renderingMode(.original)
    .frame(width: 245, height: 300)
    
    PushView(destination: Color2NewItemView(isPresenteded: self.$isPresenteded), tag: 1, selection: $selection) {
                  
                 Button(action: {self.selection = 1}) {
                 Text("Avanti")
                      .font(UIManager.einaButton)
                      .foregroundColor(.white)
                      .frame(width: 291, height: 43)

                      .background(UIManager.buttonGradient)
                      .cornerRadius(6)
                      .shadow(color: UIManager.hBlueShadow, radius: 7, x: 0.0, y: 6.0)
                 }
              }

        }
    }
  }
 }

Now I have the next view inside the Modal view, where the close button starts to stop working.现在我在模态视图中有下一个视图,关闭按钮开始停止工作。

    struct Color2NewItemView: View {

    @Binding var isPresenteded: Bool
    @State var selection: Int? = nil

    var body: some View {
      VStack(alignment: .center) {


                 Button(action: {
                       self.isPresenteded = false
                   }) {
                       Image(systemName: "xmark.circle.fill")
                       .resizable()
                       .frame(width: 30, height: 30)
                       .foregroundColor(UIManager.hBlueLight)
                   }

        Text("Second View")
                .font(UIManager.einaTitle)
                .foregroundColor(UIManager.hDarkBlue)


        Image("black-hoodie")
            .resizable()
            .renderingMode(.original)
            .frame(width: 245, height: 300)


        PushView(destination: FabricNewItemView(isPresenteded: $isPresenteded), tag: 1, selection: $selection) {

                         Button(action: {self.selection = 1}) {
                         Text("Tessuto")
                              .font(UIManager.einaButton)
                              .foregroundColor(.white)
                              .frame(width: 291, height: 43)

                              .background(UIManager.buttonGradient)
                              .cornerRadius(6)
                              .shadow(color: UIManager.hBlueShadow, radius: 7, x: 0.0, y: 6.0)
                         }
        }

                        Spacer()
                        .frame(height: 18)


                    PopView{
                        Text("Back")
                        .font(UIManager.einaBodySemibold)
                        .foregroundColor(UIManager.hGrey)
                    }

        }
    }
}

Ps.附言。 I had also to use a library called NavigationStack, since I have a custom back button on the bottom of the page, and the Navigation View doesn't let me pop back without using the back in the navigation bar.我还必须使用一个名为 NavigationStack 的库,因为我在页面底部有一个自定义后退按钮,并且导航视图不允许我在不使用导航栏中的后退的情况下弹出。

Binding can be lost on deep view hierarchy, so it is more appropriate to operate with it on the level it was received.绑定可能会在深层视图层次结构中丢失,因此在接收到的级别上使用它更合适。

Here is possible approach using EnvironmentKey (by same idea as presentationMode works)这是使用EnvironmentKey的可能方法(与presentationMode的想法相同)

Introduce helper environment key which holds some closure引入一些关闭的辅助环境键

struct DismissModalKey: EnvironmentKey {

    typealias Value = () -> ()
    static let defaultValue = { }
}

extension EnvironmentValues {
    var dismissModal: DismissModalKey.Value {
        get {
            return self[DismissModalKey.self]
        }
        set {
            self[DismissModalKey.self] = newValue
        }
    }
}

so in your top modal view you can inject into hierarchy callback to dismiss因此,在您的顶部模式视图中,您可以注入层次结构回调以解除

struct ColorNewItemView: View {

   @State var selection: Int? = nil
   @Binding var isPresented: Bool

   var body: some View {
      NavigationStackView {
          // ... other code
      }
      .environment(\.dismissModal, { self.isPresented = false} )   // << here !!
   }
}

thus this environment value now is available for all subviews, and you can use it as因此此环境值现在可用于所有子视图,您可以将其用作

struct Color2NewItemView: View {
   @Environment(\.dismissModal) var dismissModal
   
   @State var selection: Int? = nil

   var body: some View {
      VStack(alignment: .center) {
          Button(action: {
              self.dismissModal()       // << here !!
          }) {
      
      // ... other code
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM