How to perform an action after NavigationLink is tapped?

后端 未结 4 920
梦毁少年i
梦毁少年i 2020-12-10 14:29

I have a Plus button in my first view. Looks like a FAB button. I want to hide it after I tap some step wrapped in NavigationLink. So far I have something like this:

相关标签:
4条回答
  • 2020-12-10 14:46

    Another alternative I have tried. Not using simultaneousGesture, but an onDisappear modifier instead. Code is simple and It works. One downside is that those actions happen with a slight delay. Because first the destination view slides in and after this the actions are performed. This is why I still prefer @Asperi's answer where he added .simultaneousGesture(LongPressGesture) to my code.

    ForEach(0 ..< 12) {item in
        NavigationLink(destination: TransactionsDetailsView()) {
            VStack {
                HStack(alignment: .top) {
                    Text("List item")
                }
                .padding(EdgeInsets(top: 5, leading: 10, bottom: 5, trailing: 10))
                .foregroundColor(.black)
                Divider()
            }
        }
        .onDisappear(){
            self.showPlusButton = false
        }
        .onAppear(){
            self.showPlusButton = true
        }
    }
    
    0 讨论(0)
  • 2020-12-10 14:48

    I have tried an alternative approach to solving my problem. Initially I didn't use "List" because I had a problem with part of my code. But it cause another problem: PlusButton not disappearing on next screen after tapping NavigationLink. This is why I wanted to use simultaneousGesture - after tapping a link some actions would be performed as well (here: PlusButton would be hidden). But it didn't work well.

    I have tried an alternative solution. Using List (and maybe I will solve another problem later.

    Here is my alternative code. simultaneousGesture is not needed at all. Chevrons are added automatically to the list. And PlusButton hides the same I wanted.

    import SwiftUI
    
    struct BookingView: View {
    
        @State private var show_modal: Bool = false
    
        var body: some View {
            NavigationView {
                ZStack {
                    List {
                        DateView()
                            .listRowInsets(EdgeInsets())
    
                        ForEach(0 ..< 12) {item in
                            NavigationLink(destination: BookingDetailsView()) {
                                HStack {
                                    Text("Booking list item")
                                    Spacer()
                                }
                                .padding()
                            }
                        }
                    }.navigationBarTitle(Text("Booking"))
    
                    VStack {
                        Spacer()
                        Button(action: {
                            print("Button Pushed")
                            self.show_modal = true
                        }) {
                            Image(systemName: "plus")
                                .font(.largeTitle)
                                .frame(width: 60, height: 60)
                                .foregroundColor(Color.white)
                        }.sheet(isPresented: self.$show_modal) {
                            BookingAddView()
                        }
                        .background(Color.blue)
                        .cornerRadius(30)
                        .padding()
                        .shadow(color: Color.black.opacity(0.3), radius: 3, x: 3, y: 3)
                    }
                }
    
            }
        }
    
    }
    
    0 讨论(0)
  • 2020-12-10 14:49

    Yes, NavigationLink does not allow such simultaneous gestures (might be as designed, might be due to issue, whatever).

    The behavior that you expect might be implemented as follows (of course if you need some chevron in the list item, you will need to add it manually)

    import SwiftUI
    
    struct TestSimultaneousGesture: View {
        @State var showPlusButton = false
        @State var currentTag: Int?
        var body: some View {
    
            NavigationView {
                List {
                    ForEach(0 ..< 12) { item in
                        VStack {
                            HStack(alignment: .top) {
                                Text("List item")
                                NavigationLink(destination: Text("Details"), tag: item, selection: self.$currentTag) {
                                    EmptyView()
                                }
                            }
                            .padding(EdgeInsets(top: 5, leading: 10, bottom: 5, trailing: 10))
                            .foregroundColor(.black)
                            Divider()
                        }
                        .simultaneousGesture(TapGesture().onEnded{
                            print("Got Tap")
                            self.currentTag = item
                            self.showPlusButton = false
                        })
                        .simultaneousGesture(LongPressGesture().onEnded{_ in
                            print("Got Long Press")
                            self.currentTag = item
                            self.showPlusButton = false
                        })
                        .onAppear(){
                            self.showPlusButton = true
                        }
                    }
                }
            }
        }
    }
    
    struct TestSimultaneousGesture_Previews: PreviewProvider {
        static var previews: some View {
            TestSimultaneousGesture()
        }
    }
    
    0 讨论(0)
  • 2020-12-10 14:50

    I'm using the following code. I prefer it to just NavigationLink by itself because it lets me reuse my existing ButtonStyles.

    
    struct NavigationButton<Destination: View, Label: View>: View {
        var action: () -> Void = { }
        var destination: () -> Destination
        var label: () -> Label
    
        @State private var isActive: Bool = false
    
        var body: some View {
            Button(action: {
                self.action()
                self.isActive.toggle()
            }) {
                self.label()
                  .background(
                    ScrollView { // Fixes a bug where the navigation bar may become hidden on the pushed view
                        NavigationLink(destination: LazyDestination { self.destination() },
                                                     isActive: self.$isActive) { EmptyView() }
                    }
                  )
            }
        }
    }
    
    // This view lets us avoid instantiating our Destination before it has been pushed.
    struct LazyDestination<Destination: View>: View {
        var destination: () -> Destination
        var body: some View {
            self.destination()
        }
    }
    
    

    And to use it:

    var body: some View {
      NavigationButton(
        action: { print("tapped!") },
        destination: { Text("Pushed View") },
        label: { Text("Tap me") }
      )
    }
    
    0 讨论(0)
提交回复
热议问题