您可以将UIGestureRecognizer附加到多个视图吗?


228
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapTapTap:)];
[self.view1 addGestureRecognizer:tapGesture];
[self.view2 addGestureRecognizer:tapGesture];
[tapGesture release];

在上面的代码中,仅view2可识别点击。如果我注释掉第三行,则view1可以识别点击。如果我是对的,并且您只能使用一次手势识别器,那么我不确定这是一个错误还是仅需要更多文档。

Answers:


334

A UIGestureRecognizer将用于单个视图。我同意文档不完整。这UIGestureRecognizer有一个单一的view属性给它扔掉:

视图

手势识别器所附的视图。(只读)

@property(非原子,只读)UIView * view

讨论使用addGestureRecognizer:方法将手势识别器附加(或添加)到UIView对象。


11
因为向视图添加手势识别器是在运行时(相对于编译时)进行的。
TomSwift 2014年

1
我明白了,但是就像检测到我们没有使用变量一样,XCode可以根据代码告诉我们已经将同一识别器传递给多个视图,并且可以警告编码器。
佐尔坦Matók

1
关于多个视图分配相同的UITapGestureRecognizer的编译器警告是无稽之谈,因为您可能想要故意这样做,例如,如果要将敲击手势识别器从一个视图移动到另一个视图。也就是说,手势识别器不能在多个视图上使用是一个愚蠢的限制。
Erik van der Neut 2015年

1
iOS 9现在每个手势识别器都强制执行一个视图,我一直在使用下面的界面生成器方法,但是现在当我尝试使用它时,会收到以下消息(为简洁起见,一些细节被砍掉了):警告:手势识别器(<在情节提要/ xib中设置了UITapGestureRecognizer:.....>,将其添加到多个视图中(-> <UIView :; frame =(0 44; 600536); autoresize = RM + BM; poseRecognizers = < NSArray ...:>; layer = <CALayer:... >>)一次,这是从来没有被允许的,现在被强制执行。从iOS 9.0开始,它将放置在加载到的第一个视图中。
乔治·布朗

如果你在第二时间增加视图,有人之前,通过这个识别附越来越独立的自动UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didPressed:)]; [self.view1 addGestureRecognizer:tapRecognizer]; [self.view2 addGestureRecognizer:tapRecognizer];输出厂景没有手势识别器阵列; view2具有手势识别器阵列
kokos8998

48

我通过使用以下方法解决了它。

for (UIButton *aButton in myButtons) {

            UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
            longPress.minimumPressDuration=1.0;
            [aButton addGestureRecognizer:longPress];
            [longPress release];

}

然后在我的handleLongPress方法中,我只是将一个UIButton设置为等于手势识别器的视图,并根据该按钮分支我所做的事情

- (void)handleLongPress:(UILongPressGestureRecognizer*)gesture {
    if ( gesture.state == UIGestureRecognizerStateEnded ) {
        UIButton *whichButton=(UIButton *)[gesture view];
        selectedButton=(UIButton *)[gesture view];
    ....
}

1
很好的答案。如果问题是“如何将UIGestureRecognizer附加到多个视图?”,这可能是可接受的答案。
D_D

7
这(或非常接近的东西)对我不起作用。我在Interface Builder中向敲击手势识别器添加了多个视图,并将识别器连接到动作。每当点击附加视图时都会调用该动作,但是gesture.view始终是附加的最后一个视图。
Aneil Mallavarapu

这确实是一个很好的答案,也非常有帮助,并同意@MicRO +1
Dilip

2
Aneil,这是因为您没有创建手势识别器的新实例。在此答案中,循环中发生的事情是创建了手势识别器的新实例,每个实例都仅附加了一个视图。它们都可以指向同一个处理程序,然后您可以在其中查看该视图以查看被触摸了哪个视图。
Erik van der Neut

1
有人可以确认这在当前版本的Obj-C / Swift中不再有效吗?
Maxi Mus

18

如果有人需要Swift 3,请执行以下操作:根据上面的Bhavik Rathod答案。

 func setGestureRecognizer() -> UIPanGestureRecognizer {

        var panRecognizer = UIPanGestureRecognizer()

        panRecognizer = UIPanGestureRecognizer (target: self, action: #selector(pan(panGesture:)))
        panRecognizer.minimumNumberOfTouches = 1
        panRecognizer.maximumNumberOfTouches = 1
        return panRecognizer
    }

        ///set the recognize in multiple views
        view1.addGestureRecognizer(setGestureRecognizer())
        view2.addGestureRecognizer(setGestureRecognizer())

3
这基本上是为两个视图创建多个手势,仍然是相同的规则:每个手势都只能附加一个视图
Abdoelrhman

3
不,该函数在每次调用时都会创建一个手势
Abdoelrhman

2
函数名称不正确。这里的逻辑功能是获取功能。因此应将其命名为:getGestureRecognize因为这是函数的作用
David Seek

对我很好!并且代码比创建多个变量或将整个代码放入addGestureRecognizer内更干净
Codenator81 '18

11

我们可以做这样的事情,很简单

1)在您的控制器中创建以下函数(此函数将返回GestureRecognizer)

-(UITapGestureRecognizer*)setRecognizer{
     UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(openProfile)];
     [gestureRecognizer setNumberOfTapsRequired:1];
     return gestureRecognizer;
}

2)现在在多个视图中设置此识别器

[self.view1 addGestureRecognizer:[self setRecognizer]]; 
[self.view2 addGestureRecognizer:[self setRecognizer]];

当我使用两个标签代替视图时,它对我不起作用。
米希尔·奥扎

3
@Mihir Oza,它不能直接用于UILabels。因为标签对用户交互没有意义。如果要为UILabels添加手势,请在Swift中添加以下单行labelName..isUserInteractionEnabled = true。然后添加手势。
iOS

太晚了,我已经解决了。但是谢谢你的建议。您的评论将对堆栈用户有所帮助。感激!
米希尔·奥扎

1
我想setNumberOfTapsRequired:1
那条

9

不,您不应将手势识别器附加到多个视图中。

Apple文档中有以下明确信息:

手势识别器附加到视图

每个手势识别器都与一个视图相关联。相反,一个视图可以具有多个手势识别器,因为单个视图可能会响应许多不同的手势。为了使手势识别器识别在特定视图中发生的触摸,必须将手势识别器附加到该视图。

iOS事件处理指南-手势识别器 Apple开发人员库

正如其他人提到的那样,它们在某些情况下可能会起作用,这显然违反了文档说明,并且可能在将来的任何iOS版本中进行更改。

您可以做的是在要监视的视图中添加单独的手势识别器,它们可以共享一个共同的动作。


4

好吧,如果有人不想编写代码来为多个按钮(例如kwalker)添加手势视图上面已回答),并希望通过Interface Builder进行操作,这可能会对您有所帮助。

1)您可以从对象库添加长按手势识别器,就像添加其他对象(如UIButtons和UILabel)一样。

在此处输入图片说明 最初我最终只用了一个

2)为UIButton文件所有者设置引用出口,并向其发送操作。

在此处输入图片说明

注意:如果您有多个UIButton或任何其他对象,则将需要为每个对象使用单独的手势识别器。有关更多详细信息,请参阅我的这个问题。长按手势识别器上出现错误的UIButton标签


使用IB将多个UIView绑定到来宾识别器非常容易。问题是关于代码生成。
AlexeyVMP '02

3

如果您有固定的观点,我建议您做这样的事情

[self.view1 addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapTapTap:)]];
[self.view2 addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapTapTap:)]];

这样可以减少多个不同的无用变量


3

您可以在视图上创建通用扩展名,以轻松添加手势识别器。这只是一个例子,但看起来可能像这样

extension UIView {

    func setGestureRecognizer<Gesture: UIGestureRecognizer>(of type: Gesture.Type, target: Any, actionSelector: Selector, swipeDirection: UISwipeGestureRecognizer.Direction? = nil, numOfTaps: Int = 1) {
    let getRecognizer = type.init(target: target, action: actionSelector)

    switch getRecognizer {
    case let swipeGesture as UISwipeGestureRecognizer:
        guard let direction = swipeDirection else { return }
        swipeGesture.direction = direction
        self.addGestureRecognizer(swipeGesture)
    case let tapGesture as UITapGestureRecognizer:
        tapGesture.numberOfTapsRequired = numOfTaps
        self.addGestureRecognizer(tapGesture)
    default:
        self.addGestureRecognizer(getRecognizer)
    }
  }

}

要在视图上添加2次点击识别器,您只需调用:

let actionSelector = #selector(actionToExecute)
view.setGestureRecognizer(of: UITapGestureRecognizer.self, target: self, actionSelector: actionSelector, numOfTaps: 2)

您还可以轻松添加滑动识别器

view.setGestureRecognizer(of: UISwipeGestureRecognizer.self, target: self, actionSelector: actionSelector, swipeDirection: .down)

等等。只需记住目标必须链接到选择器。


2

用' <UIScrollViewDelegate>' 覆盖类

并在.m类中使用此方法:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}

此方法将帮助您在单个视图上启用多次滑动。


2

每次添加指向同一功能的手势识别器时,如何重新编写(重新创建)GestureRecognize。在以下情况下,它可以工作。我正在使用IBOutletCollection

斯威夫特2:

@IBOutlet var topicView: [UIView]!

override func viewDidLoad() {
        for view in self.topicView as [UIView] {
        view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "viewClicked:"))
    }
}

func viewClicked(recognizer: UITapGestureRecognizer) {
    print("tap")
}

-6

您可以使用此代码来实现我的视图,即xib中的imageviews。

- (void)viewDidLoad
{
    firstIV.tag = 501;
    secondIV.tag = 502;
    thirdIV.tag = 503;
    forthIV.tag = 504;

    [self addTapGesturetoImageView: firstIV];
    [self addTapGesturetoImageView: secondIV];
    [self addTapGesturetoImageView: thirdIV];
    [self addTapGesturetoImageView: forthIV];
}

-(void)addTapGesturetoImageView:(UIImageView*)iv
{
    iv.userInteractionEnabled = YES;
    UITapGestureRecognizer * textfielBGIVTapGasture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(textfielBGIVTapped:)];
    textfielBGIVTapGasture.numberOfTapsRequired = 1;
    [iv addGestureRecognizer:textfielBGIVTapGasture];
}

- (void)textfielBGIVTapped:(UITapGestureRecognizer *)recognizer {
    int tag = recognizer.view.tag-500;
    switch (tag) {
        case 1:
        {
            //firstIV tapped;
            break;
        }
        case 2:
        {
            //secondIV tapped;
            break;
        }
        case 3:
        {
            //thirdIV tapped;
            break;
        }
        case 4:
        {
            //forthIV tapped;
            break;
        }
        default: {
            break;
        }
    }
}

1
您正在创建多个手势识别器;我最初的问题是关于重用单个手势识别器,而您做不到。
kubi

1
添加500到所有视图的标签然后减去的意义是500什么?为什么不只是从1(甚至0)开始您的标签501呢?
ma11hew28 2013年

@MattDiPasquale,不要紧,如果您想1从其开始,我只是从我从我的应用程序中复制了此代码的地方501。但是,是的,请不要给0我已经读过的地方,因为它总是表明父母的观点,这样会造成并发症,相信我,我已经面对了。
Dilip 2013年

文档中的关键文本是“该视图为手势识别器建立了强大的参考”。这意味着视图拥有该手势。该手势只能有一个所有者。看到链接
Phantom59 '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.