SwiftUI 使用 onTapGesture 和 onLongPressGesture 处理按钮/视图以及释放操作

Posted

技术标签:

【中文标题】SwiftUI 使用 onTapGesture 和 onLongPressGesture 处理按钮/视图以及释放操作【英文标题】:SwiftUI handling button/view with onTapGesture and onLongPressGesture with a release action 【发布时间】:2021-05-21 14:32:07 【问题描述】:

我有一个同时具有 onTapGesture 和 onLongPressGesture 的视图。问题是我的 onLongPressGesture 的实现阻止了 onTapGesture 被调用。

这是一些代码

View()
      .onTapGesture 
           action_1
       
      .onLongPressGesture(minimumDuration: 0.5, maximumDistance: 10, pressing: 
                                    pressing in
                                    self.isPressing = pressing
                                    if (pressing) action_2
                                    if !pressing action_3
                                , perform: )

.onLongPressGesture 中的 pressing 参数检测用户是否正在按下视图/按钮,并且将始终执行 .onLongPressGesture,无论 minimumDuration 是多少。

【问题讨论】:

【参考方案1】:

编辑

Snapchat 快门,您可以点击拍照,按住按钮开始录制视频,然后松开按钮停止录制视频。这就是为什么需要执行三个操作的原因。

这很棘手。这是我所做的:

    onTapGesture,用于点击手势 LongPressGesture,延迟 0.5 秒。 0.5 秒结束后 (.onEnded),开始录制。 DragGesture,用于观察手指何时离开屏幕。发生这种情况时,请停止录制。
struct ContentView: View 
    
    /// for visual indicators
    @State var recording = false
    @State var tapped = false
    
    var body: some View 
        let longPressDrag = LongPressGesture(minimumDuration: 0.5) /// 2.
            .onEnded  _ in /// 0.5 seconds is over, start recording
                print("Long press start")
                recording = true
            
            .sequenced(before: DragGesture(minimumDistance: 0)) /// 3.
            .onEnded  _ in /// finger lifted, stop recording
                print("Long press release")
                recording = false
            
        
        Circle()
            .fill(recording ? Color.red : Color.blue)
            .opacity(tapped ? 0.5 : 1)
            .frame(width: 100, height: 100)
            
            .onTapGesture  /// 1.
                print("Tapped")
                
                tapped = true
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.3)  tapped = false 
            
            .gesture(longPressDrag)

    

结果:


旧答案:pressing 参数不适用于执行action_2 之类的操作。你可以,但它更常用于更改@State,例如在按下视图时以绿色突出显示视图。您可以在community documentation找到更多信息。

相反,您可能想要的是在 perform 闭包中调用您的操作 (action_2/print("long"))。

struct ContentView: View 
    var body: some View 
        Text("Hi")
            .font(.title)
            .onTapGesture 
                print("tap")
            
            .onLongPressGesture(minimumDuration: 0.5, maximumDistance: 10) 
                print("long")
            
    

结果:

【讨论】:

唯一的问题是我希望在我开始长按时完成一个动作,并在长按释放时开始另一个动作,这个答案不适用于该用例。 @BestFromAbove 明白了。如果我找到解决方案,将编辑我的答案。 一个帮助您理解的示例是 Snapchat 快门,您可以在其中点击拍照,按住按钮开始录制视频,然后松开按钮停止录制视频。这就是为什么需要执行三个操作的原因。 我将立即尝试实施它,感谢您为获得解决方案所做的努力! 很好的解决方法!这将是官方的答案,直到有更官方的方式来处理这些事件!感谢您在这方面的帮助。

以上是关于SwiftUI 使用 onTapGesture 和 onLongPressGesture 处理按钮/视图以及释放操作的主要内容,如果未能解决你的问题,请参考以下文章

onTapgesture 禁用 View SwiftUI 的按钮

SwiftUI .onTapGesture 从未调用过

SwiftUI onTapGesture 仅调用一次

SwiftUI:带有onTapGesture的列表单元格内的菜单触发手势

使用 SwiftUI List()、ForEach()、.onTapGesture WatchOS6 传递值的问题

swiftui 2.0 图片库 onTapgesture 只显示数组中的第一张图片