【问题标题】:Swift DragGesture tappable area detects touch outside of view?Swift DragGesture 可点击区域检测到视图之外的触摸?
【发布时间】:2021-12-20 15:46:21
【问题描述】:

我有以下代码:

struct ContentView: View {
    
    @State var progress:Float = 0.3
    
    var body: some View {
        ASlider(progress: $progress)
                .frame(width: 300, height: 40)
    }
}


struct ASlider: View {
    
    @Binding var progress: Float
    
    var body: some View {
        GeometryReader { geometry in
            ZStack(alignment: .leading) {
                Rectangle()
                    .foregroundColor(.gray)
                Rectangle()
                    .foregroundColor(.blue)
                    .frame(width: geometry.size.width * CGFloat(progress / 1))
                
            }
            .cornerRadius(12)
            .contentShape(Rectangle()) <<<---- still detects touches outside the bounds...
            .gesture(DragGesture(minimumDistance: 0)
                        .onChanged({ value in
                print("Touch: \(value)")
                progress = min(max(0, Float(value.location.x / geometry.size.width * 1)), 1)
            }))
        }
        .border(.green)
    }
}

我不明白为什么在 ZStack 边界之外检测到手势。

日志显示如下:

触摸:值(时间:2001-01-04 15:55:29 +0000,位置:(67.0, -12.333338419596316),startLocation:(130.3333282470703,-11.333338419596316),速度:SwiftUI._Velocity<__c.cgsize>(valuePerSecond:(-133.40537913839276, 10.334994031205905)))

如您所见,该位置确实检测到 Y 的负值,例如当点击滑块上方而不是内部时。

为什么在添加手势的视图边界之外检测到手势?

【问题讨论】:

  • 您可以在边框之前添加.contentShape(Rectangle()) 以尽量减少这种影响,但无论如何它会通过点(手指圈)而不是指针点来检测触摸。
  • 有趣,所以,这在任何地方都有记录吗?我现在试试内容形状,看看我做了什么。
  • 我厌倦了使用.contentShape(Rectangle()),没有运气。

标签: swiftui gesture


【解决方案1】:

当您的应用程序中只有一个手势时,这个问题或者我会说免费优势是自动开箱即用的,Apple API 尝试通过提供比开发人员计划的更多手势区域来使其更加用户友好!无法打开或关闭此功能,但您可以使用以下方法:

struct ContentView: View {
    
    @State var progress:Float = 0.3
    
    var body: some View {

        Color.white.onTapGesture { print("white") }
        .overlay(
        
            ASlider(progress: $progress)
                .frame(width: 300, height: 40)
        )
    }
}


struct ASlider: View {
    
    @Binding var progress: Float
    
    var body: some View {
        GeometryReader { geometry in
            ZStack(alignment: .leading) {
                Rectangle()
                    .foregroundColor(.gray)
                Rectangle()
                    .foregroundColor(.blue)
                    .frame(width: geometry.size.width * CGFloat(progress / 1))
            }
            .cornerRadius(12)
            .gesture(DragGesture(minimumDistance: .zero, coordinateSpace: .local)
                        .onChanged({ value in
                            print("Touch: \(value)")
                            progress = min(max(0, Float(value.location.x / geometry.size.width * 1)), 1)
                        }))
        }
        .border(Color.green)
        
    }
}

【讨论】:

  • “只有一个手势”是什么意思?这是您自己亲身经历过的事情,还是有文件说明了这一点?谢谢
  • 您问:“您所说的“只有一个手势”是什么意思?”,如果您查看您的问题,您会在代码中发现只有 1 个手势。没有第二个手势可以对此感到困惑。所以你的代码中只有一个手势!通过像我一样添加第二个作为 tapGesture 可以得到你想要的结果。更多信息:要解决这个问题,您需要告诉 Xcode 有第二个手势,请使用该区域本身,并且不要将该区域用于用户友好的手势。而且您可以只使用这样的代码.onTapGesture { },它仍然可以工作并解决问题。没有其他办法。
  • 您在回答中提出了一些“声明”,这些声明来自文档还是您在编码中观察到的内容。诸如“当您只有一个手势时”、“Apple API 尝试通过提供比开发人员计划的更多手势区域来使其更加用户友好”、“无法打开或关闭它”等声明。另外,我尝试添加“coordinateSpace:.local”,但似乎没有任何影响。我正在尝试了解我们从文档中了解到的内容以及来自反复试验的内容...此外,您在此处的代码仍然可以检测到视图范围之外的触摸。
  • 您想达到什么目的?您是在写文章还是在解决您的问题?我的答案对我有用,对你不起作用?
  • 你的答案无效
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多