【问题标题】:Swift Gesture Recognizer That Tracks Only First Touch In Continuous GestureSwift 手势识别器,仅在连续手势中跟踪第一次触摸
【发布时间】:2018-09-14 19:07:37
【问题描述】:

我正在尝试使用手势识别器来允许用户通过用一根手指拖动来调整屏幕上的视图大小......因此,我想跟踪触摸的所有变化。我最初尝试为此使用PanGestureRecognizer,但是当用户用多个手指触摸视图时遇到了问题。我只想跟踪第一次触摸(即用户在手势过程中放在屏幕上的第一根手指),但我找不到防止其他触摸干扰我跟踪第一次触摸的能力的方法。我最初的解决方案是简单地设置

recognizer.maximumNumberOfTouches = 1

但是,这会导致在第二次触摸时取消整个手势(在这种情况下,我想继续跟踪第一次触摸)。但是,当然,不将此值设置为 1 会导致手势实际跟踪多个触摸。 如何制作一个手势识别器,只跟踪手势中第一次触摸的所有变化,并且不会因屏幕上的其他触摸而取消?

【问题讨论】:

  • 如果你删除recognizer.maximumNumberOfTouches = 1这一行会发生什么?
  • 使用标准 PanGestureRecognizer,它可以跟踪两个触摸。使用我的自定义识别器,它会取消整个手势(但这样做似乎略有延迟)。
  • 摆脱 touchesMoved 的实现。
  • @matt 但是在开始之后如果用户在这种情况下触摸他的第二根手指touchBegan 将不会再次调用.. 不是吗?
  • 对,但您不希望这样做。您只想继续跟踪第一根手指,这就是会发生的事情

标签: ios swift uigesturerecognizer uipangesturerecognizer


【解决方案1】:

从您的 cmets 和回答来看,听起来您使用平移手势识别器总是错误的,并且您在动作处理程序中做错了什么。平移手势识别器的正确操作处理程序永远不会使用location(in:) 来处理任何事情。 location(in:) 为您提供所有触摸的质心,这正是您说的想要的——而且无论如何都不需要查阅它。

  • 如果您的目标是拖动视图,请使用translation(in:)

  • 如果您的目标是跟踪特定触摸的实际位置,请使用location(ofTouch:in:)

  • 如果您发现正在传递触摸并且您不希望对其进行跟踪,请致电ignore(_:for:)

【讨论】:

  • 我认为说平移手势的任何动作处理程序都不会使用location(in:) 来做任何事情有点极端;平移手势有很多用途,如果它确实与平移不兼容,则不会提供。您是正确的,对于我的用例来说,平移不是正确的手势(我在解决方案中提供的识别器是正确的),但是您的解决方案都不起作用,因为它们都不能防止手势在发生二次触摸(如果我没有设置最小触摸次数,我不知道将哪个触摸传递给location(ofTouch:in:))。
  • 你可能是对的,但这里的问题是你的问题从来没有显示你想用这个平移手势识别器做什么(现在仍然没有),所以你遇到的问题不是可重现,您自己的答案并不能回答问题本身的任何内容。
  • 好的,我将编辑我的问题以使其更清楚,因为我确实认为遇到相同问题的其他人可以从我的回答中受益。
【解决方案2】:

这是一个 UIGestureRecognizer 子类,它将跟踪用户在手势开始时在屏幕上的第一次触摸所做的所有更改,并将忽略所有其他手指而不取消手势。请注意,如果您正在使用手势识别器的功能/属性(例如 location(in:)),您可能还必须覆盖这些功能/属性。

class FirstTouchGestureRecognizer: UIGestureRecognizer {
    private var firstTouch: UITouch? = nil

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
        if firstTouch == nil {
            firstTouch = touches.first!
            self.state = .began
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
        if firstTouch != nil && touches.contains(firstTouch!) {
            self.state = .changed
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
        if firstTouch != nil && touches.contains(firstTouch!) {
            firstTouch = nil
            self.state = .ended
        }
    }
}

【讨论】:

    猜你喜欢
    • 2018-08-19
    • 1970-01-01
    • 2018-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多