SwiftUI: How to present view when clicking on a button?

后端 未结 3 715
無奈伤痛
無奈伤痛 2020-12-05 01:45

I\'m trying to make an app using Apple\'s SwiftUI and I need to have two buttons that present two different views in a single List row.

相关标签:
3条回答
  • 2020-12-05 02:09

    Update: The NavigationButton was very short lived. In beta3 it is already deprecated. I am updating the code to use its replacement: NavigationLink.

    You can present a view from all three places. Here's how:

    import SwiftUI
    
    struct ContentView: View {
    
        var body: some View {
            NavigationView {
                TopView().navigationBarTitle(Text("Top View"))
            }
        }
    }
    
    struct TopView: View {
        @State private var viewTypeA = true
    
        let detailViewA = DynamicNavigationDestinationLink(id: \String.self) { data in
                ListA(passedData: data)
        }
    
        let detailViewB = DynamicNavigationDestinationLink(id: \String.self) { data in
                ListB(passedData: data)
        }
    
        var body: some View {
                List(0..<5) { item in
                    NavigationLink(destination: ListC(passedData: "FROM ROW #\(item)")) {
                        HStack {
                            Text("Row #\(item)")
                            Spacer()
                            Text("edit")
                                .tapAction {
                                    self.detailViewA.presentedData?.value = "FROM TAP ACTION Row #\(item)"
                            }
                        }
                    }
                }.navigationBarItems(trailing: Button(action: {
                                self.detailViewB.presentedData?.value = "FROM PLUS CIRCLE"
                }, label: {
                        Image(systemName: "plus.circle.fill")
                    }))
        }
    }
    
    struct ListA: View {
        let passedData: String
    
        var body: some View {
            VStack {
                Text("VIEW A")
                Text(passedData)
            }
        }
    }
    
    struct ListB: View {
        let passedData: String
    
        var body: some View {
            VStack {
                Text("VIEW B")
                Text(passedData)
            }
        }
    }
    
    struct ListC: View {
        let passedData: String
    
        var body: some View {
            VStack {
                Text("VIEW C")
                Text(passedData)
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-05 02:17

    improved version. (Swift, iOS 13 beta 4)

    class NavigationModel : BindableObject {
        var willChange = PassthroughSubject<Void, Never>()
        var presentedData: String? {
            didSet {
                willChange.send()
            }
        }
        func dismiss() { if presentedData != nil {
            presentedData = nil
        } }
    }
    
    struct ContentView: View {
        var body: some View {
            NavigationView {
                MasterView()
            }.environmentObject(NavigationModel())
        }
    }
    
    struct MasterView: View {
    
        @EnvironmentObject
        var navigationModel: NavigationModel
        var destinationLink = DynamicNavigationDestinationLink<String, String, DetailView>(id: \.self) { data in DetailView(data: data) }
    
        var body: some View {
            List(0..<10) { index in
                Button("I am root. Tap for more details of #\(index).") {
                    self.navigationModel.presentedData = "#\(index)"
                }
            }
            .navigationBarTitle("Master")
            .onReceive(navigationModel.willChange) {
                self.destinationLink.presentedData?.value = self.navigationModel.presentedData
            }
        }
    }
    
    struct DetailView: View {
        @EnvironmentObject
        var model: NavigationModel
    
        let data: String
    
        var body: some View {
            Button("Here are details of \(data). Tap to go back.") {
                self.model.dismiss()
            }
            .navigationBarTitle("Detail \(data)")
        }
    }
    
    struct Empty : Hashable {
    }
    
    
    #if DEBUG
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
    #endif
    
    
    0 讨论(0)
  • 2020-12-05 02:21

    Much improved version (SwiftUI, iOS 13 beta 7)

    The same solution works for dismissing Modals presented with the .sheet modifier.

    import SwiftUI
    
    struct DetailView: View {
        @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
        var body: some View {
            Button(
                "Here is Detail View. Tap to go back.",
                action: { self.presentationMode.wrappedValue.dismiss() }
            )
        }
    }
    
    struct RootView: View {
        var body: some View {
            VStack {
                NavigationLink(destination: DetailView())
                { Text("I am Root. Tap for Detail View.") }
            }
        }
    }
    
    struct ContentView: View {
        var body: some View {
            NavigationView {
                RootView()
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题