首页 > 解决方案 > SwiftUI Picker and NavigationLink Gesture Conflicts

问题描述

I have a situation when I have a picker inside of a NavigationLink. However, when changing the picker toggle it also triggers the NavigationLink and you are directed to a new screen. Here is some code:

enum OptionTypes:Int,CaseIterable {
    
    case option1
    case option2
    
    var title:String  {
        switch self {
        case .option1:
            return "Option 1"
        case .option2:
            return "Option 2"
        }
    }
    
}

struct ContentView: View {
    
    @State var pickerState:OptionTypes = .option1
    @State var isActive:Bool = false
    
    var body: some View {
        
        
        NavigationView {
            
            NavigationLink(destination: Destination(), isActive:$isActive) {
                
                Picker("Options", selection: self.$pickerState) {
                    ForEach(OptionTypes.allCases, id: \.self) { type in
                        Text(type.title)
                   }
               }
                .pickerStyle(SegmentedPickerStyle())
                .padding()

            }
                        
        }
    }
}

struct Destination:View {
    
    var body: some View {
        Text("Hello World")
    }
    
}

The ideal situation is to have Picker drag and tap gestures not fire off the NavgiationLink. I've tried varying permutations of highPriorityGesture and simultaneousGesture i.e. something like:

Picker("Options", selection: self.$pickerState) {
        ForEach(OptionTypes.allCases, id: \.self) { type in
                        Text(type.title)
        }
}
.pickerStyle(SegmentedPickerStyle())
.highPriorityGesture(DragGesture(minimumDistance: 0.1, coordinateSpace: .global).onEnded { _ in

})

But this route doesn't seem to work. I also tried having the NavigationLink make use of isActive. However, that also doesn't seem to be respected. It still navigates any way without me even making the isActive true. I'm now not sure on how to have a picker function independently from the NavigationLink.

标签: swiftui

解决方案


You need to have NavigationLink separated from Picker in either way, like

  1. Make invisible

    NavigationLink(destination: Destination(), isActive:$isActive) {
        EmptyView()
    }
    
    Picker("Options", selection: self.$pickerState) {
         ForEach(OptionTypes.allCases, id: \.self) { type in
             Text(type.title)
        }
    }
     .pickerStyle(SegmentedPickerStyle())
     .padding()
    
  2. In background

    Picker("Options", selection: self.$pickerState) {
         ForEach(OptionTypes.allCases, id: \.self) { type in
             Text(type.title)
        }
    }
    .pickerStyle(SegmentedPickerStyle())
    .padding()
    .background(
      NavigationLink(destination: Destination(), isActive:$isActive) {
        EmptyView()
      })
    

推荐阅读