UITapGestureRecognizer 在移出视图并返回后被忽略

Posted

技术标签:

【中文标题】UITapGestureRecognizer 在移出视图并返回后被忽略【英文标题】:UITapGestureRecognizer is ignored after moving outside view and back in 【发布时间】:2012-06-07 18:09:37 【问题描述】:

我的UIView 中有一个UILabel 作为孩子。我将它用作状态面板,如果不需要显示任何内容,它就会滑出视图。我通过简单地将其动画到 origin.y 减去标签的高度来做到这一点。

只要显示一条消息,我就将标签滑回视图中。几秒钟的延迟后,它滑出。效果很好。

我还在标签中添加了UITapGestureRecognizer,因此用户可以立即关闭消息,而无需等待它自动消失。

我的问题是,一旦标签移出视图,手势识别器就不会触发。当标签完全在视图内并且可见时,我初始化并添加手势识别器。它第一次按预期工作。但是当消息返回时,手势识别器似乎已被删除或禁用。

我还尝试在我的动画的完整块中每次标签完全出现在屏幕上时添加一个 gr,但这也没有帮助。

有人可以向我解释一下这里发生了什么以及如何让识别器一直工作吗?

如果您需要更多信息,请告诉我。

更新

我做了一些进一步的测试,当我在 showError 调用中记录 lblError.gestureRecognizers 时得到了这个:

<UITapGestureRecognizer: 0x6b153f0; state = Possible; view = <UILabel 0x6b14fa0>; target= <(action=dismissError:, target=<OptionViewController 0x686d2a0>)>>

它与我在创建后立即得到的完全一样。所以它仍然存在,我猜触摸事件不会到达它。

更新 2

我更进一步。

问题似乎是我将标签移动到 y 坐标 0。这可能是 GestureRecognizer 代码中的一个错误,因为当我将它设置为 0.1 时它可以工作!

看起来系统“认为”标签不在视图中,因此禁用了触摸处理或其他东西。 ^^

这解决了问题的一半,但在另一侧创建了一个新问题。现在手势识别器工作了,延迟的移出动画不再被触发。

所以我认为真正的问题是,移出动画是在移入后立即触发的。即使它被延迟,它也会阻止标签接收任何类型的触摸事件。

代码

// 添加手势识别器(在 viewDidLoad 中)

UITapGestureRecognizer *errorDismissGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissError:)];
[lblError addGestureRecognizer:errorDismissGesture];

// display error
- (void)showError:(NSString *)message 
  [lblError setText:message];
  [UIView animateWithDuration:0.5 
                   animations:^(void)  
                     CGRect frame = lblError.frame;
                     frame.size.width = self.view.bounds.size.width;
                     frame.origin.y = 0;
                     lblError.frame = frame;
                    
                   completion:^(BOOL finished) 
                     [UIView animateWithDuration:0.5
                                           delay:2.0
                                         options:UIViewAnimationOptionCurveEaseOut
                                      animations:^(void) 
                                        CGRect frame = lblError.frame;
                                        frame.origin.y = -40.0f;
                                        lblError.frame = frame;
                                      
                                      completion:^(BOOL finished) ];
                   ];


- (void)dismissError:(UIGestureRecognizer *)sender 
  [UIView animateWithDuration:0.3
                   animations:^(void) 
                     CGRect frame = lblError.frame;
                     frame.origin.y = -40.0;
                     lblError.frame = frame;
                   
                   completion:^(BOOL finished) ];

感谢和问候, 托马斯

【问题讨论】:

您应该只需要添加一次。我们可以看一下代码吗? 我已经添加了代码。希望对您有所帮助。 您是否无意中将同一个识别器分配给其他地方的另一个视图? 没有。这是我创建并将其添加到标签的唯一地方。 【参考方案1】:

我终于解决了!

似乎延迟的移出动画以某种方式阻止了标签接收任何触摸事件。甚至 UIAnimationOptionAllowUserInteraction 也无济于事。

所以我用定时调用替换了延迟动画,这使得代码更易读。这就是现在的样子。

 - (void)showError:(NSString *)message 
     [lblError setText:message];
     [UIView animateWithDuration:0.5 
                     animations:^(void)  
                         CGRect frame = lblError.frame;
                         frame.size.width = self.view.bounds.size.width;
                         frame.origin.y = 0.1;
                         lblError.frame = frame;
                      
                     completion:^(BOOL finished) 
                         if (finished) 
                            [_moveOutTimer invalidate];
                             _moveOutTimer = nil;
                             _moveOutTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(dismissError:) userInfo:nil repeats:NO];
                         
                     ];


- (void)dismissError:(UIGestureRecognizer *)sender 
    [_moveOutTimer invalidate];

    [UIView animateWithDuration:0.3
                    animations:^(void) 
                         CGRect frame = lblError.frame;
                         frame.origin.y = -40.0;
                         lblError.frame = frame;
                     
                     completion:^(BOOL finished) ];

【讨论】:

以上是关于UITapGestureRecognizer 在移出视图并返回后被忽略的主要内容,如果未能解决你的问题,请参考以下文章

Flutter:ListView内部的widget值在移除item时不会更新

NVD3如何删除折线图中的Y轴,并在移除后利用Y轴的空间

如何为 UIViewController.view 中也具有 UITapGestureRecognizer 的 UIView 挑选和操作 UITapGestureRecognizer?

UITapGestureRecognizer 不适用于 UIView 动画

使用 UITapGestureRecognizer 无法识别的选择器

UIlabel 中的 UITapGestureRecognizer 错误