简体   繁体   中英

Presenting a modal view sheet from a Sub view

I am trying to present a sheet from a sub view selected from the menu item on the navigation bar but the modal Sheet does does not display. I spent a few days trying to debug but could not pin point the problem.

I am sorry, this is a little confusing and will show a simplified version of the code to reproduce. But in a nutshell, the problem seems to be a sheet view that I have as part of the main view. Removing the sheet code from the main view displays the sheet from the sub view. Unfortunately, I don't have the freedom to change the Mainview.swift

Let me show some code to make it easy to understand....

First, before showing the code, the steps to repeat the problem:

  1. click on the circle with 3 dots in the navigation bar
  2. select the second item (Subview)
  3. click on the "Edit Parameters" button and the EditParameters() view will not display

ContentView.swift (just calls the Mainview()). Included code to copy for reproducing issue:-)

struct ContentView: View {
    var body: some View {
        NavigationView {
            VStack {
                Mainview()
            }
        }
    }
}

Mainview.swift. This is a simplified version of the actual App which is quite complex and I don't have leeway to change much here unfortunately!

fileprivate enum CurrentView {
    case summary, sub
}
enum OptionSheet: Identifiable {
    var id: Self {self}
    case add
}
struct Mainview: View {
    @State private var currentView: CurrentView? = .summary
    @State private var showSheet: OptionSheet? = nil

    var body: some View {
        GeometryReader { g in
            content.frame(width: g.size.width, height: g.size.height)
                .navigationBarTitle("Main", displayMode: .inline)
        }
        //Removing the below sheet view will display the sheet from the subview but with this sheet here, it the sheet from subview does not work. This is required as these action items are accessed from the second menu item (circle and arrow) navigation baritem
        .sheet(item: $showSheet, content: { mode in
            sheetContent(for: mode)
        })
        .toolbar {
            HStack {
                trailingBarItems
                actionItems
            }
        }
    }
    
    var actionItems: some View {
        Menu {
            Button(action: {
                showSheet = .add
            }) {
                Label("Add Elements", systemImage: "plus")
            }
        } label: {
            Image(systemName: "cursorarrow.click").resizable()
            
        }
        
    }

    var trailingBarItems: some View {
        Menu {
            Button(action: {currentView = .summary}) {
                Label("Summary", systemImage: "list.bullet.rectangle")
            }
            Button(action: {currentView = .sub}) {
                Label("Subview", systemImage: "circle")
            }
        } label: {
            Image(systemName: "ellipsis.circle").resizable()
        }
    }
    
    @ViewBuilder
    func sheetContent(for mode: OptionSheet) -> some View {
        switch mode {
        case .add:
            AddElements()
        }
    }
    
    @ViewBuilder
    var content: some View {
        if let currentView = currentView {
            switch currentView {
            case .summary:
                SummaryView()
            case .sub:
                SubView()
            }
        }
    }
}

Subview.swift. This is the file that contains the button "Edit Parameters" which does not display the sheet. I am trying to display the sheet from this view.

struct SubView: View {
    @State private var editParameters: Bool = false
    var body: some View {
        VStack {
            Button(action: {
                editParameters.toggle()
            }, label: {
                HStack {
                    Image(systemName: "square.and.pencil")
                        .font(.headline)
                    Text("Edit Parameters")
                        .fontWeight(.semibold)
                        .font(.headline)
                }
            })
            .padding(10)
            .foregroundColor(Color.white)
            .background(Color(.systemBlue))
            .cornerRadius(20)
            .sheet(isPresented: $editParameters, content: {
                EditParameterView()
            })
            .padding()
            Text("Subview....")
        }
        .padding()
    }
}

EditParameters.swift. This is the view it should display when the Edit Parameters button is pressed

struct EditParameterView: View {
    var body: some View {
        Text("Edit Parameters...")
    }
}

Summaryview.swift. Nothing special here. just including for completeness

struct SummaryView: View {
    var body: some View {
        Text("Summary View")
    }
}

In SwiftUI, you can't have 2.sheet() modifiers on the same hierarchy. Here, the first.sheet() modifier is on one of the parent views to the second.sheet(). The easy solution is to move one of the.sheets() so it's own hierarchy.

You could either use ZStacks:

var body: some View {
    ZStack {
        GeometryReader { g in
            content.frame(width: g.size.width, height: g.size.height)
                .navigationBarTitle("Main", displayMode: .inline)
        }
        
        ZStack{ }
        .sheet(item: $showSheet, content: { mode in
            sheetContent(for: mode)
        })
    }
    .toolbar {
        HStack {
            trailingBarItems
            actionItems
        }
    }
}

or more elegantly:

   var body: some View {
        GeometryReader { g in
            content.frame(width: g.size.width, height: g.size.height)
                .navigationBarTitle("Main", displayMode: .inline)
        }
        .background(
            ZStack{ }
            .sheet(item: $showSheet, content: { mode in
                sheetContent(for: mode)
            })
        )
        .toolbar {
            HStack {
                trailingBarItems
                actionItems
            }
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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