【问题标题】:UILongPressGestureRecognizer stop handle without stop touchingUILongPressGestureRecognizer 停止手柄,无需停止触摸
【发布时间】:2026-01-05 04:05:02
【问题描述】:

我正在使用 UILongPressGestureRecognizer 类来处理是否选择了一项。

逻辑如下:用户在 1 秒内按下一个项目(UIView 子类)。一旦检测到手势,项目就会突出显示并可移动。

用户必须在屏幕上移动该项目而不停止触摸它。

我面临的问题是手势识别阴影 touchesBegan/Move/Ended 是项目类安排移动所必需的。

我尝试删除一旦检测到识别的手势并选择项目。但仍然向手势句柄发送消息,而不是调用 touches 方法。

任何人都知道有什么方法可以在不离开屏幕手指的情况下停止“听”手势识别器吗?

谢谢。

代码如下:

-(void)addGestures
{
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
                                               initWithTarget:self 
                                               action:@selector(handleLongPress:)];
    longPress.minimumPressDuration = iItemLongPressTime;
    [self addGestureRecognizer:longPress];
    [longPress release];
}
- (void)handleLongPress:(UILongPressGestureRecognizer*)sender { 
    if (sender.state == UIGestureRecognizerStateEnded) {

        NSLog(@"Long press Ended");
    }
    else {
        if (self.isSelected) return;

        if ([delegate respondsToSelector:@selector(singleTouch:)])
            [delegate singleTouch:self];

        [self removeGestureRecognizer:[self.gestureRecognizers objectAtIndex:0]];

        NSLog(@"Long press detected.");
    }
}

正如您在 else 分支中看到的,委托调用使所有过程都可以将此项目标记为选中,并且在删除识别器之后。

我错过了什么?

--编辑--

完成!这有效:

#pragma mark Gesture Functions
-(void)addGestures
{
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
                                               initWithTarget:self 
                                               action:@selector(handleLongPress:)];
    longPress.minimumPressDuration = iItemLongPressTime;
    [self addGestureRecognizer:longPress];
    [longPress release];
}
- (void)handleLongPress:(UILongPressGestureRecognizer*)sender { 
    if (sender.state == UIGestureRecognizerStateEnded) {

        NSLog(@"Long press Ended");
    }
    else {
        NSLog(@"Long press detected.");

        if (self.isSelected) return;

        if ([delegate respondsToSelector:@selector(singleTouch:)])
            [delegate singleTouch:self];

        [sender removeTarget:self action:@selector(handleLongPress:)];
        sender.enabled = NO;
        [self removeGestureRecognizer:sender];



    }
}

问候!

【问题讨论】:

    标签: iphone ios uigesturerecognizer


    【解决方案1】:

    自定义 UIView 类是否有自己的触摸处理代码?如果没有,一个简单的解决方案是将UILongPressGestureRecognizerallowableMovement 属性设置为CGFLOAT_MAX,或者一些大数字,然后使用手势更新回调来拖动您的自定义视图。您可以使用父视图上的- (CGPoint)locationInView:(UIView *)view 方法获取位移,并将其位置与识别器开始时的位置进行比较。

    【讨论】:

    • +1 这是最简单的解决方案。本质上,“如果您使用手势识别器,则使用手势识别器”。
    • 不需要更改allowableMovement属性;它仅用于测试失败。来自UILongPressGestureRecognizer.h "Maximum movement in pixels allowed before the gesture fails. Once recognized (after minimumPressDuration) there is no limit on finger movement for the remainder of the touch tracking" 中的 cmets
    • 您好,感谢您的回答。 UIView 子类实现 touchesBegan/Moved/Ended 以便在其父视图中操纵大小和位置。手势的使用来自于降低对每个项目的触摸敏感度的需要。目前我正在使用禁用手势识别器对象的解决方案,就像一个魅力。
    【解决方案2】:

    我的想法有两种解决方案。

    1. 对于 uiview 动画,请编写一个继承自 UIView 类的新类并实现触摸代理,而不是编写 Gustures 来处理动画(如果触摸代理未在当前类中触发)。

    2.UILongPressGestureRecognizer触发一次后成功移除。

    请参考下面的代码。如果您有任何疑问,请咨询我

    我已经完成的步骤

    当主视图加载时,我已将 UIView 作为“myView”添加到我的主视图中。

    我已经给 myView 提供了标签(你可以给 1,2,3…等)来区分被点击的视图和主视图的子视图。

    将 UILongPressGestureRecognizer 手势分配给 myView 并将目标分配为“moveMe”方法。

    当用户长按myView时,会触发“moveMe”方法。

    然后我用条件 Tag == 1 迭代 mainView 子视图

    我已经从 subview 中删除了 UILongPressGestureRecognizer。我们可以知道 Tagged 1 main-view subView 是 myView。

    所以 NSLog(@"gesture removed");和 NSLog(@"moveMe");将只登录一次控制台。

    NSLog(@"touchesBegan");会先触发,而不是触发“moveMe”方法。

    然后 NSLog(@"touchesBegan");移除手势后总会触发。 “moveMe”方法永远不会触发。

    代码

        - (void)viewDidLoad {    
            //Adding to UIView to main view when application is loading.
             UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(20, 20, 80, 80)];        
             myView.backgroundColor = [UIColor viewFlipsideBackgroundColor];
              myView.tag = 1; //adding a tag to identify it.
            //Adding Long Press Gesture to the UIView.
            UILongPressGestureRecognizer *myGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(moveMe:)];
            [myView addGestureRecognizer:myGesture];
            [myGesture release];
            myGesture = nil;   
           [self.view addSubview:myView];   
           [myView release];
            myView = nil;    
            [super viewDidLoad];
        }    
    
        //Method to trigger when user pressed long on the added UIView.
    
     -(void)moveMe:(id)sender
     { 
          for (UIView *subViews in [self.view subviews]) 
          { 
                if (subViews.tag == 1) { 
                     [subViews removeGestureRecognizer:sender];
                     NSLog(@"gesture removed");
                 }    
             }    
             NSLog(@"moveMe");
        }    
     -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
     {
         NSLog(@"touchesBegan");
     }
    

    或请参考Disable gesture recognizer iOS

    【讨论】:

    • 请尽量详细描述您的问题
    • 我尝试将发送者作为参数发送到删除方法,但仍然无法正常工作。