ios-runtime攔截touch事件,展現用戶觸摸效果

【展現效果說明】ios

  對 app 操做錄屏時,展現出手指在 app 上的觸摸效果能夠看到具體點擊狀況,感受這樣比較直觀方便,也不用作視頻後期了。app

  這裏簡單用 runtime 實現了一個這樣的效果,不須要修改任何代碼,只要將 UIWindow+Touch.m 分類導入工程便可。動畫

  展現效果以下:spa

    

 

【實現思路】code

  1. 要攔截到全部的點擊事件,獲取點擊相對於屏幕的位置。ios中事件分發中點擊事件應該是這樣的: 系統第一個獲得點擊事件 -> 分發給application -> 分發給 window -> window 內的子 view 層層遍歷。orm

  2. 只是一個小功能,要讓這個功能可控,不要對原有代碼進行改動。用 runtime 交換系統方法進行touch事件攔截,在分發事件時加入本身的一些代碼。視頻

  3. 拿到觸摸點的位置後建立 view 展現一些動畫效果就能夠。對象

  上面第1點中能夠知道,事件在application中進行攔截最靠譜,由於系統第一個分發就是給它,但這裏操做都是UI相關,因此UI相關事件放在 window 上進行處理比較合適。因此這裏就是交換的 window 對象的 sendEvent: 方法。blog

 

【代碼  新建 UIWindow + Touch 分類,在 .m 文件中交換 sendEvent 方法,同時加上本身處理的代碼,主要是在獲取點擊x,y的位置,而後添加一個view,加上一點動畫,最終就有了上述效果。 UIWindow + Touch.m 代碼以下:事件

#import "UIWindow+Touch.h
#import <objc/runtime.h>
@implementation UIWindow (Touch) + (void)load {
  // 交換方法 Method m1
= class_getInstanceMethod([self class], @selector(sendEvent:)); Method m2 = class_getInstanceMethod([self class], @selector(ljs_sendEvent:)); method_exchangeImplementations(m1, m2); } - (void)ljs_sendEvent:(UIEvent *)event { [self ljs_sendEvent:event];
  // 對點擊事件進行處理 [self dealTouch:
event]; } - (void)dealTouch:(UIEvent *)event { UITouch *touch = event.allTouches.anyObject; if (touch.phase == UITouchPhaseEnded) { return; } static CGFloat width = 20; if (event.type == UIEventTypeTouches) { CGPoint point = [event.allTouches.anyObject locationInView:self]; CGFloat oringX = point.x - width / 2; CGFloat oringY = point.y - width / 2; CGRect rect = CGRectMake(oringX, oringY, width, width); UIView *blackV = [[UIView alloc] initWithFrame:rect]; blackV.alpha = 0.3; blackV.layer.cornerRadius = width / 2; blackV.backgroundColor = [UIColor purpleColor]; [self addSubview:blackV]; [self bringSubviewToFront:blackV]; // 設置動畫 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"]; animation.duration = 0.3; animation.fromValue = @1; animation.toValue = @2; animation.fillMode = @"backwards"; animation.removedOnCompletion = YES; [blackV.layer addAnimation:animation forKey:@"an1"]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.27 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [blackV removeFromSuperview]; }); } } @end
相關文章
相關標籤/搜索