UITouch
UITouch的屬性
觸摸產(chǎn)生時所處的窗口
- @property(nonatomic,readonly,retain) UIWindow *window;
觸摸產(chǎn)生時所處的視圖
- @property(nonatomic,readonly,retain) UIView *view;
短時間內(nèi)點按屏幕的次數(shù),可以根據(jù)tapCount判斷單擊、雙擊或更多的點擊
- @property(nonatomic,readonly) NSUInteger tapCount;
記錄了觸摸事件產(chǎn)生或變化時的時間,單位是秒
- @property(nonatomic,readonly) NSTimeInterval timestamp;
當前觸摸事件所處的狀態(tài)
- @property(nonatomic,readonly) UITouchPhase phase;
UITouch的方法
(CGPoint)locationInView:(UIView *)view;
返回值表示觸摸在view上的位置
這里返回的位置是針對view的坐標系的(以view的左上角為原點(0, 0))
調(diào)用時傳入的view參數(shù)為nil的話,返回的是觸摸點在UIWindow的位置(CGPoint)previousLocationInView:(UIView *)view;
該方法記錄了前一個觸摸點的位置
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//獲取UITouch對象
UITouch *touch = [touches anyObject];
//獲取當前的x
CGPoint cur = [touch locationInView:self];
//獲取之前位置的x
CGPoint pre = [touch previousLocationInView:self];
//獲取偏移的x
CGFloat offsetX = cur.x - pre.x;
CGFloat offsetY = cur.y = pre.y;
//改變view的位置
self.transform = CGAffineTransformTranslate(self.transform, offsetX, offsetY);
}
事件的產(chǎn)生和傳遞
- 發(fā)生觸摸事件后,系統(tǒng)會將該事件放到UIApplication管理的事件隊列中。
- UIApplication會從事件隊列中觸摸事件,并傳給單例的UIWindow。
- UIWindow使用hitTest:withEvent:方法查找最合適的view
如果父控件不能接受觸摸事件,那么子控件就不可能接受到觸摸事件
觸摸事件的傳遞是從父控件傳遞到子控件
UIView不接收觸摸事件的三種情況
- UIView不接收觸摸事件的三種情況
- userInteractionEnabled = NO 不接收用戶交互
- hidden = YES 隱藏
- alpha = 0.0~0.1 透明
- UIImageView的userInteractionEnabled默認是No,因此UIImageView以及它的子控件默認是不能接受觸摸事件的
hitTest:withEvent:方法
//調(diào)用時間:當事件傳遞給控件的時候,就會調(diào)用控件的這個方法, 作用:去尋找最合適的view
//觸摸事件產(chǎn)生后 ->放到UIApplication隊列中 ->從UIApplication取出觸摸事件 ->傳給UIWindow ->UIWindow調(diào)用hitTest方法
//在hitTest方法中需要判斷 1.當前控件能否接受事件 2.觸摸的點在不在當前控件 3.從后往前遍歷子控件
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
// 1.判斷當前控件能否接收事件
if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) return nil;
// 2. 判斷點在不在當前控件
if ([self pointInside:point withEvent:event] == NO) return nil;
// 3.從后往前遍歷自己的子控件
NSInteger count = self.subviews.count;
for (NSInteger i = count - 1; i >= 0; i--) {
UIView *childView = self.subviews[i];
// 把當前控件上的坐標系轉(zhuǎn)換成子控件上的坐標系
CGPoint childP = [self convertPoint:point toView:childView];
UIView *fitView = [childView hitTest:childP withEvent:event];
if (fitView) { // 尋找到最合適的view
return fitView;
}
}
// 循環(huán)結(jié)束,表示沒有比自己更合適的view
return self;
}