Is it possible to have multiple NavigationLinks per row in a List SwiftUI?

后端 未结 2 1856
北海茫月
北海茫月 2020-12-16 05:44

I can\'t use multiple NavigationLinks in the same row of a List.

It looks like the navigation stack is totally messed up, because you tap once and it goes to multipl

相关标签:
2条回答
  • 2020-12-16 06:10

    As the others mentioned, why 2 NavigationLinks in 1 cell. The issue is with multiple buttons and gesture in general for the Cell. I guess it is expected 1 Button/NavigationLink max per cell. As you noticed, on your video, you tap on a NavigationLink but your full Cell got the gesture (highlighted), which in return impact the other Buttons/NavigationLinks.

    Anyhow, you can have it working, the 2 NavigationLinks in 1 cell, with a hack. Below I have created SGNavigationLink, which I use for my own app which solve your issue. It simply replace NavigationLink and based on TapGesture, so you will lose the highlight.

    NB: I slightly modified your ListCellView, as the Spacer within my SGNavigationLink was creating an internal crash.

    struct ListCellView: View {
    
        var body: some View {
            VStack {
    
                HStack{
                    SGNavigationLink(destination: TestDestination1())  {
                        Text("Test Destination 1")
                            .frame(width: 140, height: 50)
                            .background(RoundedRectangle(cornerRadius: 7.0).strokeBorder(Color.green, lineWidth: 3.0))
                    }
    
                    Spacer()
                }
    
                HStack{
                SGNavigationLink(destination: TestDestination2())  {
                    Text("Test Destination 2")
                        .frame(width:140, height: 50)
                        .background(RoundedRectangle(cornerRadius: 7.0).strokeBorder(Color.purple, lineWidth: 3.0))
    
                }
                Spacer()
                }
            }
        }
    }
    
    
    
    struct SGNavigationLink<Content, Destination>: View where Destination: View, Content: View {
        let destination:Destination?
        let content: () -> Content
    
    
        @State private var isLinkActive:Bool = false
    
        init(destination: Destination, title: String = "", @ViewBuilder content: @escaping () -> Content) {
            self.content = content
            self.destination = destination
        }
    
        var body: some View {
            return ZStack (alignment: .leading){
                if self.isLinkActive{
                    NavigationLink(destination: destination, isActive: $isLinkActive){Color.clear}.frame(height:0)
                }
                content()
            }
            .onTapGesture {
                self.pushHiddenNavLink()
            }
        }
    
        func pushHiddenNavLink(){
            self.isLinkActive = true
        }
    }
    
    0 讨论(0)
  • 2020-12-16 06:11

    I am not sure about why do you need multiple Navigationlinks (duplicate code). You can use a data source that will hold the required properties of the list [title, color, id etc] and based on the id, call the desired View. Reuse the same code. Here is an example.

    struct TestList: View {
        var body: some View {
            List { // <- Use Data source 
                ForEach(0..<2) { index in
                     ListCellView(index: index)
                }
            }
        }
    }
    
    struct ListCellView: View {
        var index: Int
        var body: some View {
             return   NavigationLink(destination: ViewFactory.create(index))  {
                    Text("Test Destination 1")
                        .frame(width: 140, height: 50)
                        .background(RoundedRectangle(cornerRadius: 7.0).strokeBorder(Color.green, lineWidth: 3.0))
                }
        }
    }
    
    
    class ViewFactory {
       static func create(_ index: Int) -> AnyView {
            switch index {
            case 0:
                return AnyView(TestDestination1())
            case 1:
                return AnyView(TestDestination2())
            default:
               return AnyView(EmptyView())
            }
        }
    }
    
    struct TestDestination1: View {
        var body: some View {
            Text("Test Destination 1")
        }
    }
    
    struct TestDestination2: View {
        var body: some View {
            Text("Test Destination 2")
        }
    }
    
    0 讨论(0)
提交回复
热议问题