当触摸时,UIPanGestureRecognizer 立即执行某些操作。

21

如果我错过了一些显而易见的东西,请提前谅解,因为我是iOS新手。

我正在创建一个拼图,我希望在触摸时逐个增大拼图块的尺寸,在松开时逐个减小。

目前我的代码如下:

-(IBAction)handlePan:(UIPanGestureRecognizer *)recognizer{
  if(recognizer.state == UIGestureRecognizerStateBegan)
  else if(recognizer.state == UIGestureRecognizerStateEnded)
}

当平移开始(即状态开始)时,拼图块会增大;当平移结束时,拼图块会减小(符合预期)。我希望在用户触摸拼图块并且拼图块移动之前将其大小增加。这在选择单词中的字母时可以在“Words With Friends”中看到。

我已经尝试过:

-(IBAction)handleTap:(UITapGestureRecognizer *)recognizer{
  if(recognizer.state == UIGestureRecognizerStateBegan)
  else if(recognizer.state == UIGestureRecognizerStateEnded)
}

只有在手指抬起后,这才会增加拼图块的大小。

我的问题是:

是否有一种方法可以在手指触摸拼图块后增加拼图块的大小,然后继续进行平移手势。

提前致谢。


是的,“中间”状态缺失了。您必须跟踪它以查看它们是否已经开始移动(translationInView)。 - Marcus Adams
7个回答

41

我也需要这样做,Jake的建议对我来说完美地解决了问题。如果有人将来遇到类似问题,以下是我的UIPanGestureRecognizer子类实现(头文件保持不变):

#import "ImmediatePanGestureRecognizer.h"
#import <UIKit/UIGestureRecognizerSubclass.h>

@implementation ImmediatePanGestureRecognizer

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [super touchesBegan:touches withEvent:event];
    self.state = UIGestureRecognizerStateBegan;
}

@end

这就是你需要的全部内容 - 只要你在视图上放下手指,它就会立即触发,在任何方向上移动一个点时立即更新,并在常规UIPanGestureRecognizer (如translationInViewvelocityInView)触发之前提供相同的功能,而不会破坏任何现有功能。


适用于 Swift 5,2023年复制粘贴

import UIKit // (nothing extra needed to import with Swift5)

fileprivate class ImmediatePanG: UIPanGestureRecognizer {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
        super.touchesBegan(touches, with: event)
        state = .began
    }
}

你真是个天才,我从来没想过要这样做。不过手势识别器会以相同的状态值调用两次其选择器函数... - Nate Symer
1
如果我们在具有touchesBegan方法的UIview上实现ImmediatePanGestureRecognizer,该如何给它设置优先级? - Reza.Ab
1
@GeorgeWS,如果您看到此消息,我已经简单地修复了您在这里的“著名答案”中的当前Swift版本!显然,随意回滚、编辑等,祝好! - Fattie
1
@NateSymer,你可以添加if state == .began { return }。然而,在我看来,我不会这样做。我们正在添加一个“新状态”。(将其视为“.earlyBegan”或“.downBegan”或“.specialStackoverflowBegan”!!!)它的性质与苹果决定的“通常.began”不同,例如可能发生在不同的x位置等。我想更完整的解决方案是添加一个新状态(“.downBegan”),然后在上游您可以根据需要进行处理。因此,我会这样说:添加if state == .began { return }以使其“不报告‘通常’开始”,如果需要的话。 - Fattie

9

Swift 3/4/5 解决方案

class InstantPanGestureRecognizer: UIPanGestureRecognizer {

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

}

注意,对于任何在此搜索的人,请小心添加“if state == .began { return }”代码。这意味着您正在替换状态,而不是添加状态。请参见选中答案下的讨论。 - Fattie

8

我已经实现了George WS的答案。经过一些测试,我意识到在初始触摸结束之前发生的额外触摸事件没有被正确处理。以下是我的更新实现方式。它有点天真,但可以防止由UIGestureRecognizerStateBegan多次发生导致的奇怪行为。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    if (self.state >= UIGestureRecognizerStateBegan) {
        return;
    }

    [super touchesBegan:touches withEvent:event];
    self.state = UIGestureRecognizerStateBegan;
}

2

Thanks George WS & Derrick Hathaway

Swift 2.2

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent) {
  if (self.state == UIGestureRecognizerState.Began) {
    return
  }
  super.touchesBegan(touches, withEvent: event)
  self.state = UIGestureRecognizerState.Began;
}

你需要将以下内容添加到你的桥接头文件中:

#import <UIKit/UIGestureRecognizerSubclass.h>

2
根据文档,只有在“允许的手指最小数量(minimumNumberOfTouches)已移动足够以被认为是平移”时,UIPanGestureRecognizer才会进入UIGestureRecognizerStateBegan状态。如果您希望触摸时立即发生某些事情,可以尝试子类化UIPanGestureRecognizer并重写touchesBegan:withEvent:

2

我在UIScrollView的一个视图中绘制。我使用UIPanGestureRecognizer在该视图中绘制。这个UIPanGestureRecognizer的minimumNumberOfTouches和maximumNumberOfTouches都设置为1。

我使用scrollView的UIPinchGestureRecognizer和UIPanGestureRecognizer进行平移和缩放。scrollView的UIPanGestureRecognizer的minimumNumberOfTouches和maximumNumberOfTouches都设置为2。

我使用了George WS的解决方案,发现绘画开始得很快,但很难识别用于缩放的捏合手势和用于平移的双指拖动手势。我稍微改变了解决方案,并使用touchesMoved来识别绘画的开始。缩放和平移被更好地识别了。

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
    super.touchesMoved(touches, with: event)
    state = UIGestureRecognizer.State.began
}

那也是我的情况。谢谢你的想法! - atereshkov

0

我正在尝试做类似的事情,我一直在努力解决的问题是使用视图的touchesBegan:withEvent:来执行我想要发生的操作,即用户触摸屏幕时立即执行。然后手势处理程序接管一旦触摸变成手势。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接