如何让步进和长按共存?

Posted

技术标签:

【中文标题】如何让步进和长按共存?【英文标题】:How to get stepper and longpress to coexist? 【发布时间】:2013-12-30 20:59:39 【问题描述】:

我尝试使用长按手势和配置为持续更新的步进器设置视图。长按不会出现步进的连续特性。现在,我已经禁用了长按。我想我不需要它。但是为了将来参考,我如何允许两者共存?

为了清楚起见,这是我尝试这个时屏幕的设置方式。

应用设置了一个简单的视图控制器。 一个子视图被添加到这个视图中(本来可以是一个控制器,但我只是把它做成了一个 UIView)。 向此子视图添加了多个标签和步进器。 步进器被连接成插座和动作。 长按识别器已添加到 IB 的主视图中。 为了完整起见,还在 IB 的主视图中添加了轻击手势。

按预期点击主视图功能。点击步进器按预期工作。主视图上的长按按预期运行。长按步进器不会。

我修改了长按调用的代码以检查子视图的框架,如果触摸位置在该矩形内,则不采取行动,但这并没有什么不同。在那种情况下,我没有尝试让长按失败,但我想接下来我会尝试。编辑:好的,也许不是。似乎没有用于此的 API。但是,有this kludge,我不会尝试。

附件是带有倒置调用树的分析器的屏幕截图,因此您可以看到每个项目被调用的内容。

darkStepped: 是步进器调用的 IBAction。如果步进器由手势识别器触发,我不希望在调用树中看到手势识别器吗?

【问题讨论】:

请提供一些代码,以便更清楚您要做什么... 不确定要包含哪种代码。除了 IBAction 之外,步进器没有其他代码,它可以通过点击工作,但不能在按住时工作。长按是在 IB 中拖入的长按手势。当我在 IB 中移除长按时,步进器以连续模式工作。我不认为问题出在我的代码上,而在于知道步进器在幕后正在发生什么样的活动。例如,步进器是否使用与我的视图的长按冲突的长按手势识别器? 【参考方案1】:

如果步进器由手势识别器触发,我不希望在调用树中看到手势识别器吗?

堆栈跟踪显示步进器的_updateCount 方法是通过计时器调度的。

这可能与步进器具有“自动增量”模式有关,只要您按住它,它就会以给定的(变化的)速率更新。因此,步进器不是简单地调用_updateCount,而是设置一个计时器来处理此行为。

无论出于何种原因使用计时器,计时器都会解释为什么您在堆栈跟踪中看不到手势识别器。

在您的情况下,步进器会发生触摸,处理它们,而不是将它们转发给与其连接的任何手势识别器。

这可以解释如下,虽然这个 sn-p 没有明确提到与UIStepper 控件相关的长按识别器:

根据Apple Docs:

与其他用户界面控件交互 在 ios 6.0 及更高版本中,默认控制操作可防止重叠的手势识别器行为。例如,按钮的默认操作是单击。如果您将单击手势识别器附加到按钮的父视图,并且用户点击按钮,则按钮的操作方法会接收触摸事件而不是手势识别器。这仅适用于与控件的默认操作重叠的手势识别,其中包括:

单指单击 UIButton、UISwitch、UIStepper、UISegmentedControl 和 UIPageControl。

...

如果您有这些控件之一的自定义子类并且想要更改默认操作,请将手势识别器直接附加到控件而不是父视图。然后,手势识别器首先接收到触摸事件。与往常一样,请务必阅读 iOS 人机界面指南,以确保您的应用提供直观的用户体验,尤其是在覆盖标准控件的默认行为时。

因此,您似乎可以将手势识别器直接附加到控件上(可能您需要将UIStepper 子类化才能使其工作,我不确定如何解释最后一段)。希望这不会禁用步进器的基本工作(但也许会)。

【讨论】:

插座连接,手势识别器未选中。以这种方式似乎看不到任何手势识别器。我想过使用gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:,但我不知道如何处理步进器的手势识别器。 您应该以编程方式检查您的 UIStepper 插座,以查看其 gestureRecognizers 属性是否有任何内容……而不是来自 Interface Builder…… 嗯。我会试试的。同时,我粘贴了分析器中显示调用树的屏幕截图。我很惊讶我在那里没有看到任何看起来像手势识别器的东西。 sender.gestureRecognizers 为零(sender 是步进器对象)。 我明白了。请检查我编辑的答案。 Apple 文档中明确提到了这种情况。【参考方案2】:

再次仔细查看 Apple 的文档后,我找到了解决方案。我将视图控制器作为委托添加到长按手势识别器

self.longPress.delegate = self;

(当然还有在界面中添加<UIGestureRecognizerDelegate>,然后在视图控制器中添加这个方法:

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch 
   // Determine if the touch is inside the custom subview
   if (gestureRecognizer == self.longPress) 
      CGPoint touchLocation = [touch locationInView:self.view];
      if (CGRectContainsPoint(self.antControl.frame, touchLocation)) 
         return NO;
      
   
   return YES;

这样,当长按发生在self.antControl 的框架内时,手势识别器甚至不会被调用,这是问题中提到的子视图。

【讨论】:

以上是关于如何让步进和长按共存?的主要内容,如果未能解决你的问题,请参考以下文章

ViewPager 和长按

使用 QAbstractButton::autoRepeat 时如何区分按下、释放和长按

Android:如何在listView上的项目中结合滑动手势和长按

具有单按和长按事件的 UIButton 快速

点击和长按无法正常工作

结合向下滑动和长按