6

我尝试重新实现我正在使用的 SegmentedControlers,因为它们在 Xcode 11 beta 5 中已被弃用。这花了一段时间,但我得到了我想要的外观。但是,当我用 onTapGesture() 替换 tapAction 时,选择器停止工作。

下面的代码显示了问题。注释掉 pickerStyle 会得到一个与 onTapGesture() 一起工作的轮子选择器

import SwiftUI

var oneSelected = false
struct ContentView: View {
    @State var sel = 0
    var body: some View {
        VStack {
            Picker("Test", selection: $sel) {
                Text("A").tag(0)
                Text("B").tag(1)
                Text("C").tag(2)
            }
            .pickerStyle(SegmentedPickerStyle())
            Picker("Test", selection: $sel) {
                Text("A").tag(0)
                Text("B").tag(1)
                Text("C").tag(2)
            }
            .pickerStyle(SegmentedPickerStyle())
            .onTapGesture(perform: {
                oneSelected = (self.sel == 1)
            })
            Text("Selected: \(sel)")
        }
    }
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

我希望 Picker().pickerStyle(SegmentedPickerStyle()) 应该像 SegmentedController() 一样工作。

4

3 回答 3

4

您添加的tapGesture内容会干扰选择器的内置点击手势识别,这就是为什么在点击.onTapGesture选择器时运行代码但选择器本身没有响应点击的原因。在您的情况下,我建议采用不同的方法:将符合的视图模型传递给ObservableObject您的ContentView,并让它包含一个@Published用于选择器选择的变量。然后向该变量添加一个属性观察器,以检查所选选项是否为 1。

例如:

class ViewModel: ObservableObject {
    @Published var sel = 0 {
        didSet {
            oneSelected = oldValue == 1
        }
    }
    var oneSelected = false
}

SceneDelegate.swift, 或任何地方ContentView声明:

ContentView().environmentObject(ViewModel())

ContentView.swift

@EnvironmentObject var env: ViewModel
var body: some View {
    VStack {
        Picker("Test", selection: $env.sel) {
            Text("A").tag(0)
            Text("B").tag(1)
            Text("C").tag(2)
        }
        .pickerStyle(SegmentedPickerStyle())
        Picker("Test", selection: $env.sel) {
            Text("A").tag(0)
            Text("B").tag(1)
            Text("C").tag(2)
        }
        .pickerStyle(SegmentedPickerStyle())
        Text("Selected: \(sel)")
    }
}

注意:根据我的经验,在以前的 beta 中添加一个 tapGesture 会SegmentedControl导致SegmentedControl没有响应,所以我不确定为什么它在以前的版本中对你有用。从 SwiftUI beta 5 开始,我认为没有办法为手势分配优先级。

编辑:您可以使用.highPriorityGesture()让您的手势优先于视图中定义的手势,但您的手势具有更高的优先级会导致您的问题。但是,您可以使用.simultaneousGesture(),我认为这可以解决您的问题,但我认为它在 SwiftUI Beta 5 中还不能完全发挥作用。

于 2019-07-30T15:58:51.077 回答
2
class IndexManager: ObservableObject {
    @Published var index = 0 {
        didSet {
            publisher.send(index)
        }
    }
    let publisher = PassthroughSubject<Int, Never>()
}

struct SegmentedPickerView: View {

    private let strings = ["a", "b", "c"]
    @ObservedObject private var indexManager = IndexManager()

    var body: some View {
        Picker("", selection: $indexManager.index) {
            ForEach(strings, id: \.self) {
                Text($0).tag(self.strings.firstIndex(of: $0)!)
            }
        }.pickerStyle(SegmentedPickerStyle())
            .onReceive(indexManager.publisher) { int in
                print("onReceive \(int)")
        }
    }
}
于 2019-12-21T15:09:57.070 回答
0

我能够在 onTapGesture 的以下条件下使用它

@State private var profileSegmentIndex = 0    

Picker(selection: self.$profileSegmentIndex, label: Text("Music")) {
                    Text("My Posts").tag(0)
                
                Text("Favorites").tag(1)
            }
            .onTapGesture {
                if self.profileSegmentIndex == 0 {
                    self.profileSegmentIndex = 1
                } else {
                    self.profileSegmentIndex = 0
                }
            }
于 2020-11-03T06:27:44.593 回答