SwiftUI 中的选择器选择和翻译冲突

Posted

技术标签:

【中文标题】SwiftUI 中的选择器选择和翻译冲突【英文标题】:Picker selection and translation conflict in SwiftUI 【发布时间】:2021-02-12 07:02:18 【问题描述】:

我有一个带有 Picker 的可移动 VStack。当我想从 Picker 中选择不同的选项时,我不能,因为 SwiftUI 认为我想使用 DragGesture,因此我的 Picker 被锁定!我的 DragGesture 有 minimumDistance: 0 但是当我改变这个值时它也不能解决问题,另一方面我喜欢有 minimumDistance: 0 所以它甚至不是一个选项为我解决增加 minimumDistance 的问题,所以我需要帮助找到方法,谢谢。

struct ContentView: View 
    var body: some View 
        
        StyleView()
        
    


struct StyleView: View 
    
    @State private var location: CGSize = CGSize()
    @GestureState private var translation: CGSize = CGSize()
    @State private var styleIndex: Int = 0
    let styles: [String] = ["a", "b", "c"]

    var body: some View 

        VStack 

            Picker(selection: $styleIndex, label: Text("Style")) 

                ForEach(styles.indices, id:\.self)  index in
                    
                    Text(styles[index].description)

                
 
            
            .pickerStyle(SegmentedPickerStyle())
            .padding()

            Text("selected style: " + styles[styleIndex])
        
        .padding()
        .background(Color.red)
        .cornerRadius(10)
        .padding()
        .position(x: location.width + translation.width + 200, y: location.height + translation.height + 100)
        .gesture(DragGesture(minimumDistance: 0)
                    .updating($translation)  value, state, _ in
                        state = value.translation
                    
                    .onEnded  value in
                        location = CGSize(width: location.width + value.translation.width, height: location.height + value.translation.height)
                    )
        
        
    

【问题讨论】:

我知道你在你的问题中说你不想要任何最小距离,但是你确定它对你不起作用 - 将它设置为1让选择器为我工作,似乎是一个非常小的副作用。我不确定它怎么会是 0,因为它永远无法区分拖动和点击。 我的意思是在 Picker 上拖动,通常我们可以用拖动来改变 Picker,如果我选择了 1 并且正如你所说的非常小,但是在选择器上拖动不起作用,你试过吗? 啊——我没明白那一点。好的,知道了。 例如如果使用minimumDistance=200就可以解决问题,但是在VStack上没有很好的拖动体验!拖动必须大于 200 才能开始拖动! 【参考方案1】:

DragGesture 在用户按下视图并至少移动一定距离时触发。因此,这会创建一个带有拖动手势的选取器,当用户将其移动至少 10 点时触发(它应该大于 0,否则它如何知道点击和拖动)

struct StyleView: View 
    
    @State private var location: CGSize = CGSize()
    @GestureState private var translation: CGSize = CGSize()
    @State private var styleIndex: Int = 0
    let styles: [String] = ["a", "b", "c"]

    var body: some View 

        VStack 

            Picker(selection: $styleIndex, label: Text("Style")) 

                ForEach(styles.indices, id:\.self)  index in
                    
                    Text(styles[index].description)

                
 
            .gesture(DragAndTapGesture(count: styles.count, selected: $styleIndex).horizontal)
            .pickerStyle(SegmentedPickerStyle())
            .padding()
            Text("selected style: " + styles[styleIndex])
        
        .padding()
        .background(Color.red)
        .cornerRadius(10)
        .padding()
        .position(x: location.width + translation.width + 200, y: location.height + translation.height + 100)
        .gesture(DragGesture(minimumDistance: 1)
                    .updating($translation)  value, state, _ in
                        state = value.translation
                    
                    .onEnded  value in
                        location = CGSize(width: location.width + value.translation.width, height: location.height + value.translation.height)
                    )
        
        
    




struct DragAndTapGesture 
    var count: Int
    @Binding var selected: Int
    
    init(count: Int, selected: Binding<Int>) 
        self.count = count
        self._selected = selected
    
    
    var horizontal: some Gesture 
        DragGesture().onEnded  value in
            if -value.predictedEndTranslation.width > UIScreen.main.bounds.width / 2, self.selected < self.count - 1 
                self.selected += 1
            
            if value.predictedEndTranslation.width > UIScreen.main.bounds.width / 2, self.selected > 0 
                self.selected -= 1
            
        
    

【讨论】:

我的意思是在 Picker 上拖拽,通常我们可以用拖拽来改变 Picker,如果我选择了 10 并且正如你所说的很小,但是在 Picker 上拖拽不起作用,你试过吗? 好的,我明白了,请参阅我编辑的答案。它可能会对你有所帮助。 我认为没有尊重,它不能解决问题 你现在检查了吗? 您是否也检查过设备,因为我可以轻松拖动以及点击选择器,并且拖动后值也会发生变化。增加 padding 区域,并更改选取器的背景颜色,使其易于区分。

以上是关于SwiftUI 中的选择器选择和翻译冲突的主要内容,如果未能解决你的问题,请参考以下文章

选择器(SegmentedPickerStyle)中的选择效果不佳 - SwiftUI

如何让 SwiftUI 中的选择器输出选择的值?

来自先前选择器的选择器值 - CoreData/SwiftUI

SwiftUI 选择器分隔符

SwiftUI 选择器为所选项目和选择视图分隔文本

表单中的 SwiftUI 选择器 - 索引超出范围