我还注意到,当我尝试读取 UIPanGestureRecognizer 上的 shouldBegin 方法中的值时,我只能在用户移动一点后(即手势开始识别平移时)看到它的位置。知道这个平移手势实际上从哪里开始是非常有用的,这样我就可以决定它是否应该识别。
如果你不想继承 UIGestureRecognizer 视图,你有两个选择:
- UILongPressGestureRecognizer,并将延迟设置为 0
- UIPanGestureRecognizer,并在 shouldReceiveTouch 中捕获起点
如果您有其他手势(例如点击、双击等),那么您可能需要选项 2,因为延迟为 0 的长按手势识别器会导致无法正确识别其他手势。
如果您不关心其他手势,只希望平移正常工作,那么您可以使用延迟为 0 的 UILongPressGestureRecognizer 并且更容易维护,因为您不需要手动跟踪开始观点。
解决方案一:UILongPressGestureRecognizer
适合:简单
不利于:与其他手势处理程序配合得很好
创建手势时,请确保将minimumPressDuration设置为0
。这将确保您的所有委托方法(例如应该开始)将正确接收第一次触摸。
因为 UILongPressGestureRecognizer 是一个连续手势识别器(与离散手势识别器相反),您可以通过处理UIGestureRecognizer.State.changed属性来处理移动,就像使用 UIPanGestureRecognizer(它也是一个连续手势识别器)一样。本质上,您将这两个手势结合起来。
let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(gestureHandler(_:))
gestureRecognizer.minimumPressDuration = 0
解决方案 2:UIPanGestureRecognizer
适合:与其他手势识别器配合得很好
不利于:需要更多的努力来保存启动状态
步骤:
首先,您需要注册为委托并监听 shouldReceiveTouch 事件。
一旦发生这种情况,将触摸点保存在某个变量中(不是手势点!)。
当需要决定是否真的要开始手势时,请阅读此变量。
var gestureStartPoint: CGPoint? = nil
// ...
let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(gestureHandler(_:))
gestureRecognizer.delegate = self
// ...
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
gestureStartPoint = touch.location(in: self)
return true
}
警告:确保阅读touch.location(in: self)
而不是gestureRecognizer.location(in: self)
因为前者是准确获取起始位置的唯一方法。
您现在可以gestureStartPoint
在任何您想要的地方使用,例如应该开始:
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return isValidStartPoint(gestureStartPoint!)
}