iOS 触摸事件

2019-04-03  本文已影响0人  小的小碰撞

响应者对象

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

// 触摸结束前,某个系统事件(例如电话呼入)会打断触摸过程,系统会自动调用view的下面方法

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

UITouch

- (CGPoint) locationInView:(UIView *)view;
// 返回值表示触摸在view上的位置
// 这里返回的位置是针对view的坐标系的(以view的左上角为原点(0,0))
// 调用时传入的参数为nil 时,返回的是在UIWindow的位置
-(CGPoint)previusLocationInView:(UIView *)view;
// 改方法记录上一个触摸点的位置

UIEvent

触摸开始:- (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

UIView的拖拽

// 当手指在view上移动的时候
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"%s",__func__);

    // 获取UITouch对象
    UITouch *touch = [touches anyObject];

    // 获取当前点
    CGPoint curP = [touch locationInView:self];

    // 获取上一个点
    CGPoint preP = [touch previousLocationInView:self];

    // 获取x轴偏移量
    CGFloat offsetX = curP.x - preP.x;

    // 获取y轴偏移量
    CGFloat offsetY = curP.y - preP.y;

    // 修改view的位置(frame,center,transform)
    self.transform = CGAffineTransformTranslate(self.transform, offsetX, offsetY);


    //CGAffineTransformTranslate  是相对于上一个的位置
    //CGAffineTransformMakeTranslation(<#CGFloat tx#>, <#CGFloat ty#>)  每一次都是清零的
//    self.transform = CGAffineTransformMakeTranslation(offsetX, 0);

}
事件的产生和传递

如何找到最合适的控件来处理事件

如果父控件不能接受事件,那么它的子控件也不能接受触摸事件

image.png

事件的产生和传递底层实现

// 因为所有的视图类都是继承BaseView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
//    NSLog(@"%@--hitTest",[self class]);
//    return [super hitTest:point withEvent: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];
        
        // 把当前控件上的坐标系转换成子控件上的坐标系
       CGPoint childP = [self convertPoint:point toView:childView];
        
       UIView *fitView = [childView hitTest:childP withEvent:event];
        
        
        if (fitView) { // 寻找到最合适的view
            return fitView;
        }
        
        
    }
    
    // 循环结束,表示没有比自己更合适的view
    return self;
    
}

/// 练习1
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    // 当前坐标系上的点转换到按钮上的点
    CGPoint btnP = [self convertPoint:point toView:self.btn];

    // 判断点在不在按钮上
    if ([self.btn pointInside:btnP withEvent:event]) {
        // 点在按钮上
        return self.btn;
    }else{
        return [super hitTest:point withEvent:event];
    }
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{

    // 当前控件上的点转换到chatView上
    CGPoint chatP = [self convertPoint:point toView:self.chatView];

    // 判断下点在不在chatView上
    if ([self.chatView pointInside:chatP withEvent:event]) {
        return self.chatView;
    }else{
        return [super hitTest:point withEvent:event];
    }



}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    // 获取UITouch
    UITouch *touch = [touches anyObject];

    // 获取当前的点
    CGPoint curP = [touch locationInView:self];

    // 获取上一个的点
    CGPoint preP = [touch previousLocationInView:self];

    // 获取偏移量
    CGFloat offsetX = curP.x - preP.x;
    CGFloat OffsetY = curP.y - preP.y;

    // 修改控件的位置
    CGPoint center = self.center;
    center.x += offsetX;
    center.y += OffsetY;

    self.center = center;

}

事件传递的完整过程

上一篇 下一篇

猜你喜欢

热点阅读