【问题标题】:Identifying the Type of Touch Gestures from UIEvent Object从 UIEvent 对象识别触摸手势的类型
【发布时间】:2013-02-06 09:55:58
【问题描述】:

有没有办法获得触发 UIEvent 的触摸手势类型?所以,假设我用 hitTest:withEvent: 拦截了一个手势。如何识别触发此方法的触摸(捏合、点击、滑动等)?

我可以从 UIEvent 子类型中获取远程事件的类型,即使设备被摇晃,但触摸事件没有参数...

你如何识别这些?

【问题讨论】:

  • @blub:实际上,它没有重复——这里的问题是关于 hitTest:withEvent: 中的低级触摸检测
  • 可能是“我的错,对不起”

标签: iphone ios hittest uievent


【解决方案1】:

您必须自己进行触摸分析。

这并不难,但它不是为你完成的。这是我实际使用的一些代码的示例。它并不意味着作为一个全面的解决方案。它仅在非常具体的上下文(我的应用程序)中检测基本的点击/滑动/捏手势,并使用一种相当不酷的机制来传递手势(通知)。因此,它可能适用于您的情况,也可能不适用,但我希望它能让您了解所需的内容。

NSSet* allTouches = [event allTouches];
UITouch* touch = [allTouches anyObject];
UIView* touchView = [touch view];

        if (touch.phase == UITouchPhaseBegan) {

            _initialView = touchView;
            startTouchPosition1 = [touch locationInView:self];
            startTouchTime = touch.timestamp;

            if ([allTouches count] > 1) {
                startTouchPosition2 = [[[allTouches allObjects] objectAtIndex:1] locationInView:self];
                previousTouchPosition1 = startTouchPosition1;
                previousTouchPosition2 = startTouchPosition2;
            }
        }

        if (touch.phase == UITouchPhaseMoved) {

            if ([allTouches count] > 1) {
                CGPoint currentTouchPosition1 = [[[allTouches allObjects] objectAtIndex:0] locationInView:self];
                CGPoint currentTouchPosition2 = [[[allTouches allObjects] objectAtIndex:1] locationInView:self];

                CGFloat currentFingerDistance = CGPointDist(currentTouchPosition1, currentTouchPosition2);
                CGFloat previousFingerDistance = CGPointDist(previousTouchPosition1, previousTouchPosition2);
                if (fabs(currentFingerDistance - previousFingerDistance) > ZOOM_DRAG_MIN) {
                    NSNumber* movedDistance = [NSNumber numberWithFloat:currentFingerDistance - previousFingerDistance];
                    if (currentFingerDistance > previousFingerDistance) {
//                          NSLog(@"zoom in");
                        [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_ZOOM_IN object:movedDistance];
                    } else {
//                          NSLog(@"zoom out");
                        [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_ZOOM_OUT object:movedDistance];
                    }
                }
            }
        }

        if (touch.phase == UITouchPhaseEnded) {
            CGPoint currentTouchPosition = [touch locationInView:self];

            // Check if it's a swipe
            if (fabsf(startTouchPosition1.x - currentTouchPosition.x) >= SWIPE_DRAG_HORIZ_MIN &&
                fabsf(startTouchPosition1.x - currentTouchPosition.x) > fabsf(startTouchPosition1.y - currentTouchPosition.y) &&
                touch.timestamp - startTouchTime < 0.7) 
            {
                // It appears to be a swipe.
                if (startTouchPosition1.x < currentTouchPosition.x) {
                        NSLog(@"swipe right");
                    [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_SWIPE_RIGHT object:self];
                } else {
                        NSLog(@"swipe left");
                    [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_SWIPE_LEFT object:self];
                }
            } else {
                //-- else, check if it's a single touch
                if (touch.tapCount == 1) {
                    NSDictionary* uInfo = [NSDictionary dictionaryWithObject:touch forKey:@"touch"];
                    [[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_TAP object:self userInfo:uInfo];                        
                }/* else if (touch.tapCount > 1) {
                    handle multi-touch
                }
                */
            }

            startTouchPosition1 = CGPointMake(-1, -1);
            _initialView = nil;
        }

        if (touch.phase == UITouchPhaseCancelled) {
            _initialView = nil;
//          NSLog(@"TOUCH CANCEL");
        }

【讨论】:

  • 我会试一试,稍后再报告。谢谢!
  • 请考虑我的代码只是一个 sn-p:它并不是一个全面的解决方案。它仅在非常具体的上下文(我的应用程序)中检测基本的点击/滑动/捏手势,并使用一种相当不酷的机制来传递手势(通知)。我希望它能让您了解需要什么。
  • 我已经完成了您的解决方案的尝试。问题是它不适用于 hitTest:withEvent: 因为 [event allTouches] 返回一个空对象。不过,如果我将您的代码放入常规的 touchesBegan:withevent: 方法中,它就可以工作。
  • 实际上,我在自定义 UIWindow sendEvent: 中使用该代码,并且定义了触摸。我不知道您要做什么,但是您可以自定义 UIWindow 并在那里进行手势检测吗?
  • 我会考虑的...还是谢谢你!如果没有其他人回复,我会接受你的回答。
【解决方案2】:

您需要自己分析触摸(触摸次数和位置)。另一种更简单的方法是添加对应的手势识别器来获取对应的类型。所有触摸事件的事件类型都是UIEventSubtypeNone

【讨论】:

    【解决方案3】:

    从 iOS 7 开始,有一个委托方法可以让您了解 URL 交互,称为 textView(_:shouldInteractWith:in:interaction:)

    https://developer.apple.com/documentation/uikit/uitextviewdelegate/1649337-textview

    【讨论】:

      猜你喜欢
      • 2018-08-19
      • 1970-01-01
      • 2018-12-31
      • 2017-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多