这几天一直在纠结怎么监听滑动手势,获得滑动的距离,但是就是没有一篇文章解决我的问题,自己摸索了好久,才知道怎么搞,这么有纪念意义,一定要记录一下。
我写的SDK,需要监听用户滑动屏幕的距离,如果重写touchesBegan这一类方法,有两大缺点:一、如果客户的app里有重写这些方法,则会冲突;二、如果用户手势点击到了响应优先级高的地方(比如按钮),则不会执行这些方法,达不到我们想要的效果。因此,只能拦截系统方法sendEvent了,也就是苹果所谓的黑魔法。
那么这样,又怎么获得滑动的长度呢?
拦截方法就可以获得UIEvent对象,从而得到触摸事件UItouch对象,UITouch对象有个phase属性,这个属性有四个取值:UITouchPhaseBegan、UITouchPhaseMoved、UITouchPhaseStationary、UITouchPhaseEnded、UITouchPhaseCancelled。其中的began、moved、ended就可以实现我们想要的结果了。
拦截到系统的sendEvent,先执行我们的事件处理方法,然后执行系统的方法,还是上代码吧!!!
staticfloatswipeLength =0;
staticCGPointprePoint;
@implementationWindowHook
+ (instancetype)sharedWindowHook
{
staticWindowHook*windowHook =nil;
staticdispatch_once_tpredicate;
dispatch_once(&predicate, ^{
windowHook = [[selfalloc]init];
});
returnwindowHook;
}
+ (void)initialize
{
Method sendEvent=class_getInstanceMethod([UIWindowclass],@selector(sendEvent:));
Method sendEventMySelf=class_getInstanceMethod([selfclass],@selector(sendEventHooked:));
IMPsendEventImp =method_getImplementation(sendEvent);
class_addMethod([UIWindowclass],@selector(sendEventOriginal:), sendEventImp,method_getTypeEncoding(sendEvent));
IMPsendEventMySelfImp =method_getImplementation(sendEventMySelf);
class_replaceMethod([UIWindowclass],@selector(sendEvent:), sendEventMySelfImp,method_getTypeEncoding(sendEvent));
}
对事件怎么处理呢,看下面:
- (void)sendEventHooked:(UIEvent*)event
{
[selfperformSelector:@selector(sendEventOriginal:)withObject:event];
NSSet*touches = [eventallTouches];
UITouch*touch = [touchesanyObject];
UITouchPhasephase = touch.phase;
UIWindow*keyWindow = [[UIApplicationsharedApplication]keyWindow];
CGPointcurrentPoint = [touchlocationInView:keyWindow];
NSLog(@"(%f,%f)",currentPoint.x,currentPoint.y);
switch(phase) {
caseUITouchPhaseBegan:
{
prePoint= currentPoint;
}
break;
caseUITouchPhaseMoved:
{
floatdistance =fabs(currentPoint.y-prePoint.y);
swipeLength=swipeLength+distance;
prePoint= currentPoint;
}
break;
caseUITouchPhaseEnded:
{
NSLog(@"%f",swipeLength);
swipeLength=0;
}
break;
default:
break;
}
}
我理解的还是比较浅显,有错的地方,还请大家指出来啊!!!
网友评论