在SwiftUI中检测DragGesture取消 [英] Detect DragGesture cancelation in SwiftUI

查看:97
本文介绍了在SwiftUI中检测DragGesture取消的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有一个添加了DragGesture的Rectangle,并且想要跟踪手势的开始,更改和结束.问题是当我在执行手势时将另一根手指放在矩形上时,第一个手势停止调用onChange处理程序,并且不触发onEnded处理程序. 同样,处理程序也不会为那只第二只手指开火.

So I have a Rectangle with an added DragGesture and want to track gesture start, change and ending. The issue is when I put another finger on the Rectangle while performing the gesture, the first gesture stop calling onChange handler and does not fire onEnded handler. Also the handlers doesn't fire for that second finger.

但是如果我在不移开前两根手指的情况下放了第三根手指,则该手势的处理程序将开始触发(以此类推,即使按下也可以取消奇数行)

But if I place third finger without removing previous two the handlers for that gesture start to fire (and so on with even presses cancel out the odd ones)

这是一个错误吗?有没有办法检测到第一个手势已取消?

Is it a bug? Is there a way to detect that the first gesture was canceled?

Rectangle()
  .fill(Color.purple)
  .gesture(
    DragGesture(minimumDistance: 0, coordinateSpace: .local)
      .onChanged() { event in
        self.debugLabelText = "changed \(event)"
      }
      .onEnded() { event in
        self.debugLabelText = "ended \(event)"
      }
  )

推荐答案

感谢@krjw提供了手指数均匀的提示

Thanks to @krjw for the hint with an even number of fingers

在Gesture框架中,这似乎是一个问题,即使我们没有指定它应该监听这些手势,它也试图检测一堆手势.

This appears to be a problem in the Gesture framework for attempting to detect a bunch of gestures even if we didn't specify that it should be listening for them.

由于文档非常少,我们只能真正猜测这里的预期行为和生命周期是什么(恕我直言-这似乎是一个错误)-但可以解决.

As the documentation is infuriatingly sparse we can only really guess at what the intended behaviour and lifecycle here is meant to be (IMHO - this seems like a bug) - but it can be worked around.

定义

func onDragEnded() {
  // set state, process the last drag position we saw, etc
}

然后将几种手势组合成一个手势,以涵盖我们未指定的基础

Then combine several gestures into one to cover the bases that we didn't specify

let drag = DragGesture(minimumDistance: 0)
      .onChanged({ drag in
       // Do stuff with the drag - maybe record what the value is in case things get lost later on 
      })
      .onEnded({ drag in
        self.onDragEnded()
      })

     let hackyPinch = MagnificationGesture(minimumScaleDelta: 0.0)
      .onChanged({ delta in
        self.onDragEnded()
      })
      .onEnded({ delta in
        self.onDragEnded()
      })

    let hackyRotation = RotationGesture(minimumAngleDelta: Angle(degrees: 0.0))
      .onChanged({ delta in
        self.onDragEnded()
      })
      .onEnded({ delta in
        self.onDragEnded()
      })

    let hackyPress = LongPressGesture(minimumDuration: 0.0, maximumDistance: 0.0)
      .onChanged({ _ in
        self.onDragEnded()
      })
      .onEnded({ delta in
        self.onDragEnded()
      })

    let combinedGesture = drag
      .simultaneously(with: hackyPinch)      
      .simultaneously(with: hackyRotation)
      .exclusively(before: hackyPress)

/// The pinch and rotation may not be needed - in my case I don't but 
///   obviously this might be very dependent on what you want to achieve

对于simultaneouslyexclusively可能有更好的组合,但是至少对于我的用例(这类似于操纵杆),似乎正在做

There might be a better combo for simultaneously and exclusively but for my use case at least (which is for something similar to a joystick) this seems like it is doing the job

还有一个GestureMask类型可能已经完成了工作,但是没有有关其工作方式的文档.

There is also a GestureMask type that might have done the job but there is no documentation on how that works.

这篇关于在SwiftUI中检测DragGesture取消的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆