【问题标题】:Detect touch down & touch up in a view containing UIControls在包含 UIControls 的视图中检测 touch down 和 touch up
【发布时间】:2011-06-17 23:06:34
【问题描述】:

我正在尝试检测用户何时在视图中向下和向上触摸。该视图包含一些按钮和其他 UIKit 控件。我想检测这些触摸事件但不消耗它们。

我尝试了两种方法,但都不够:

首先,我添加了一个覆盖 -touchesBegan:withEvent: 和 -touchesEnded:withEvent: 的透明覆盖,并使用

将事件转发给下一个响应者
[self.nextResponder touchesBegan:touches withEvent:event]

但是,UIKit 对象似乎忽略了所有转发的事件。

接下来,我尝试覆盖 -pointInside:withEvent: 和 -hitTest:withEvent: 。这对于检测触摸 down 事件非常有效,但是在触摸 up 时不会调用 pointInside:: 和 hitTest:: (即 [[[event allTouches] anyObject] 阶段] 是永远不等于 UITouchPhaseEnded )。

在不干扰与底层 UIControls 交互的情况下检测 touch down 和 touch up 事件的最佳方法是什么?

【问题讨论】:

  • 我看不出响应者为什么会忽略 touchesBegan:withEvent: 只是因为它已经被发送到具有相同事件的其他东西。这违背了响应者链的意义。你确定nextResponder 正在返回一些东西吗?
  • @Peter "UIKit 框架的类不是为接收未绑定到它们的触摸而设计的;在编程术语中,这意味着 UITouch 对象的 view 属性必须持有对框架对象以便处理触摸。如果您想有条件地将触摸转发给应用程序中的其他响应者,所有这些响应者都应该是您自己的 UIView 子类的实例。 (developer.apple.com/library/ios/#documentation/EventHandling/…)

标签: iphone cocoa-touch touches touch-event


【解决方案1】:

根据Event Handling Guide for iOS 你有 3 个选择:

1) 继承 UIWindow 以覆盖 sendEvent:

2) 使用覆盖视图

3) 设计让您不必这样做...所以更像是 2 个选项。

这里是一个苹果的简化例子,使用 UIWindow 子类;

1) 将 NIB 中的窗口类更改为 UIWindow 的子类。 2)将此方法放入.m文件中。

- (void)sendEvent:(UIEvent *)event
{
    NSSet * allTouches = [event allTouches];

    NSMutableSet *began = nil;
    NSMutableSet *moved = nil;
    NSMutableSet *ended = nil;
    NSMutableSet *cancelled = nil;

    // sort the touches by phase so we can handle them similarly to normal event dispatch
    for(UITouch *touch in allTouches) {
        switch ([touch phase]) {
            case UITouchPhaseBegan:
                if (!began) began = [NSMutableSet set];
                [began addObject:touch];
                break;
            case UITouchPhaseMoved:
                if (!moved) moved = [NSMutableSet set];
                [moved addObject:touch];
                break;
            case UITouchPhaseEnded:
                if (!ended) ended = [NSMutableSet set];
                [ended addObject:touch];
                break;
            case UITouchPhaseCancelled:
                if (!cancelled) cancelled = [NSMutableSet set];
                [cancelled addObject:touch];
                break;
            default:
                break;
        }

        // call our methods to handle the touches
        if (began)
        {
            NSLog(@"the following touches began: %@", began);
        };
        if (moved)
        {
            NSLog(@"the following touches were moved: %@", moved);
        };
        if (ended)
        {
             NSLog(@"the following touches were ended: %@", ended);
        };
        if (cancelled) 
        {
             NSLog(@"the following touches were cancelled: %@", cancelled);
        };
    }
    [super sendEvent:event];
}

它有太多的输出,但你会明白的......并且可以使你的逻辑适合你想要的地方。

【讨论】:

  • 如果我在叠加层中检测到触摸,调用 [super touchesBegan:] 不会将事件转发到下面的视图。如果我在父视图中检测到触摸,则子 UIButton 会消耗这些触摸,并且我的 touchesBegan: 永远不会被调用。
  • 你说得对,UIView 正在吞噬事件,我修改了 UIWindow 子类的苹果示例。
  • 谢谢,我会研究这种方法。 (我不知道你为什么被否决。)
猜你喜欢
  • 1970-01-01
  • 2012-08-31
  • 2011-02-05
  • 1970-01-01
  • 1970-01-01
  • 2011-04-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多