UIView只收集move轨迹,不接收“单击”、“长按”事件

参考:

[1]http://developer.apple.com/library/ios/#documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/MultitouchEvents/MultitouchEvents.html#//apple_ref/doc/uid/TP40009541-CH3-SW20


情景:

如果你有一个全屏、透明的UIView盖在目前界面的上面,这个uivew不做显示用,只是收集用户在屏幕上的move 时的点。但要允许用户在点击和长按时,全屏view背后的view做出反应,这时全屏的view相当于不存在。


解决方案:

方案一

设置该全屏、透明view的 userInteractionEnabled 为NO,截获UIApplication的SendEvent ,在其中记录move时的所有点。这时,用户所有的touch事件都按原来执行,这个全屏的view真像不存在一样。

利用objective-c runtime相关代码核心实现如下:

    //Swap the implementations of our interceptor and the original sendEvent:
    Method oldMethod = class_getInstanceMethod(self, @selector(sendEvent:));
    Method newMethod = class_getInstanceMethod(self, @selector(interceptSendEvent:));
    method_exchangeImplementations(oldMethod, newMethod);

简单的说就是创建一个UIApplication的类别,然后通过method_exchangeImplementations 替换sendEvent,让系统调用sendEvent时首先调用我们自己定义的方法,然后在其中记录move的point点,最后调用系统原来的sendEvent方法即可。

方案二

设置该全屏、透明view的 userInteractionEnabled 为YES,重写父类的四个事件处理方法

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;


- (void)forwardTouchBegan:(id)obj
{	
	NSArray* array = (NSArray*)obj;
	NSSet*   touches = [array objectAtIndex:0];
	UIEvent* event   = [array objectAtIndex:1];
	[[self nextResponder] touchesBegan:touches withEvent:event];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
	touchMove_ = NO;
	[self performSelector:@selector(forwardTouchBegan:) withObject:[NSArray arrayWithObjects:touches,event,nil] afterDelay:0.5];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
	touchMove_ = YES;
	[[self class] cancelPreviousPerformRequestsWithTarget:self];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
	if (!touchMove_)
	{
		[[self nextResponder] touchesEnded:touches withEvent:event];
	}
}


这里主要应用了这两个方法,在begin时延时调用forwardTouchBegan ,在move时取消 调用。这里用延时方法有效地解决了 无法判断用户touch begin时接下去是否会move的问题。 参考【1】中列出了苹果文档中利用此方法来解决 单击还是双击的问题,只不过这时在touch end启动延时调用performSelector ,在touch begin时根据tapcount判断是否取消调用。

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;

+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget;

不过方案二 跟 背景view与全屏viewview层次相关,如果两则不同的window 则  通过[self nextResponder] 背景view可能还是接收不到事件。



你可能感兴趣的:(UIView只收集move轨迹,不接收“单击”、“长按”事件)