我有一个带有点击手势识别器的 View 。此 View 的 subview 是我的自定义类的实例,该类继承自UIControl。我遇到一个问题,即UIControl子类有时会在不应该允许的时候将触摸事件传递给父 View 。

在UIControl子类中,我重写了这些函数(代码在Swift中)

override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool
{
    return true
}

override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool
{
    // The code here moves this UIControl so its center is at the touchpoint
    return true
}

override func endTrackingWithTouch(touch: UITouch,withEvent event: UIEvent)
{
    // Something important happens here!
}

如果用户在UIControl内向下触摸,在X和Y方向上拖动控件,然后提起屏幕,则该系统运行良好。在这种情况下,将调用所有这三个函数,并且发生“重要的事情”。

但是,如果用户使用UIControl进行触摸,仅在X方向上拖动控件,然后将其提离屏幕,那么我们就会遇到问题。前两个函数被调用,但是当触点从屏幕上移开时,轻击手势识别器被调用,而endTrackingWithTouch不被调用。

如何确保始终调用endTrackingWithTouch?

最佳答案

我以一种我认为是骇客的方式解决了这个问题,但是鉴于UIGestureRecognizer的工作原理,实际上别无选择。

发生的事情是轻击手势识别器正在取消控件的跟踪并注册轻击手势。这是因为当我水平拖动时,我碰巧只是拖动了很短的距离,这被解释为轻击手势。

UIControl跟踪时必须禁用轻击手势识别器:

override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool
{
    pointerToSuperview.pauseGestureRecognizer()
    return true
}

override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool
{
    // The code here moves this UIControl so its center is at the touchpoint
    return true
}

override func endTrackingWithTouch(touch: UITouch,withEvent event: UIEvent)
{
    // Something important happens here!
    pointerToSuperview.resumeGestureRecognizer()
}

override func cancelTrackingWithEvent(event: UIEvent?)
{
    pointerToSuperview.resumeGestureRecognizer()
}

在superview的类中:
pauseGestureRecognizer()
{
    tapGestureRecognizer.enabled = false
}

resumeGestureRecognizer()
{
    tapGestureRecognizer.enabled = true
}

之所以有效,是因为我没有处理多点触摸(我可以在使用UIControl跟踪触摸时不接收点击触摸事件,这是可以的)。

理想情况下,控件不必告诉 View 暂停手势识别器-手势识别器不应该首先干预控件的触摸!但是,即使将手势识别器的cancelsTouchesInView设置为false也无法防止这种情况。

关于ios - UIControl endTrackingWithTouch不被调用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25939178/

10-11 17:20