UI触摸手势,事件的分发传递

#import "TouchView.h"


@implementation TouchView {

    BOOL _isInside;

}


 


- (instancetype)initWithFrame:(CGRect)frame {


    if (self = [super initWithFrame:frame]) {//创建的时候是传入的大小

        

        //响应单点触摸,默认是YES

        //self.userInteractionEnabled = NO;

        

        //响应多点触摸,默认是NO

        self.multipleTouchEnabled = YES;

        

        //创建红色子视图

        self.redView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 50, 50)];

        self.redView.backgroundColor = [UIColor redColor];

        [self addSubview:self.redView];

        

        //超出部分进行裁剪

        self.clipsToBounds = YES;


    }

    

    return  self;

    

}



//只有继承自UIResponder的类才能够复写这些方法来监听触摸事件

//触摸开始时调用此方法

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

    

    NSLog(@"触摸开始");

    

    //判断是单点触摸还是多点触摸

//    if (touches.count == 1) {

//        NSLog(@"一根手指触摸");

//    } else if (touches.count == 2) {

//        NSLog(@"两根手指触摸");

//    }

    

    

    //UITouch的常用属性

    UITouch *touch = [touches anyObject];

    

    //1.window

//    NSLog(@"%@", self.window);

//    NSLog(@"%@", touch.window);

//    

    2.view

//    NSLog(@"%@", touch.view);

//    NSLog(@"%@", self);

    

//    3.tapCount

   

    NSInteger count = touch.tapCount;

    if (count  == 1) {

        

        [self performSelector:@selector(singleTap) withObject:nil afterDelay:0.3];

      

    } else if (count == 2) {

        

        [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(singleTap) object:nil];//取消先前的做的请求

        [self doubleTap];

        

    }

    //获取当前触摸点在视图上的坐标,slef是灰色视图,然后是根据灰色视图来确定坐标的

    CGPoint p = [touch locationInView:self];

    NSLog(@"p=%@", NSStringFromCGPoint(p));

    

    //self中的p点坐标转化为toView(redView)的坐标。

    CGPoint p2 = [self convertPoint:p toView:self.redView];//眼里只有红色视图,那么点击P的坐标自然清楚,将点击点的坐标转换成红色视图的坐标

    NSLog(@"p2=%j@", NSStringFromCGPoint(p2));//将坐标转换成string。

    

    CGPoint p3 = [self convertPoint:p toView:self.superview];

    NSLog(@"p3=%@", NSStringFromCGPoint(p3));

    

    //fromView(self)上的坐标点转化为self.superView上的坐标

    //convertPoint转变坐标

    CGPoint p4 = [self.superview convertPoint:p fromView:self];//将self的坐标转换为父视图的坐标。

    NSLog(@"p4=%@", NSStringFromCGPoint(p4));

    

    

    //判断当前的点击点是否在某个视图范围内,首先要有点的位置,然后有这个图的位置

    _isInside = [self.redView pointInside:p2 withEvent:event];

    if (_isInside) {

        

        [UIView animateWithDuration:0.3 animations:^{

            self.redView.transform = CGAffineTransformMakeScale(1.3, 1.3);//形变放大

        }];

       

    }

    

}


//按住红色视图,图标放大1.3倍,红色视图随手指移动,抬起手指还原。


- (void)singleTap {

    NSLog(@"单击");

}


- (void)doubleTap {

    NSLog(@"双击");

}


//触摸点移动时调用此方法

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

    

    //NSLog(@"触摸移动");

    

    

    if (_isInside) {

        UITouch *touch = [touches anyObject];

        CGPoint currentP = [touch locationInView:self];//移动后的坐标

        

        CGPoint previousP = [touch previousLocationInView:self];//移动前的坐标

        

        //移动距离

        CGFloat moveX = currentP.x - previousP.x;

        CGFloat moveY = currentP.y - previousP.y;

        

        //设置redViewframe

        CGRect frame = self.redView.frame;//子视图的frame

        frame.origin.x += moveX;

        frame.origin.y += moveY;

        

        self.redView.frame = frame;

        


    }

    

    

    

}


//触摸结束时调用

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

    [UIView animateWithDuration:0.3 animations:^{

        self.redView.transform = CGAffineTransformIdentity;//表示返回图形原象

    }];

    

}


//被其它事件取消时调用

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

    

    [UIView animateWithDuration:0.3 animations:^{

        self.redView.transform = CGAffineTransformIdentity;

    }];

}

------------------------事件的分化传递------------------------------------

事件的分化传递:接受的是触摸的那个视图如果不接受则由其父视图或者controller接受。

#import "RootView.h"

#import "RedView.h"

#import "GreenView.h"


@implementation RootView



- (instancetype)initWithFrame:(CGRect)frame {

    if (self = [super initWithFrame:frame]) {

        

        RedView *rdView = [[RedView alloc] initWithFrame:CGRectMake(20, 40, 100, 100)];

        rdView.backgroundColor = [UIColor redColor];

        [self addSubview:rdView];

                           

        GreenView *greenView = [[GreenView alloc] initWithFrame:CGRectMake(150, -40, 100, 100)];

        greenView.backgroundColor = [UIColor greenColor];

        [self addSubview:greenView];

        

    }

    

    return self;

}


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

    

    NSLog(@"%@接收到事件", [self class]);//当前类的名字

    

}


还原hitTest:withEvent这个方法进行事件分发传递的过程

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    

   

    for (UIView *subView in self.subviews) {

        //坐标系的转换,以上面的各个子视图为坐标原点,然后得出各个坐标,convertPoint是点击的坐标

        CGPoint subViewPoint = [self convertPoint:point toView:subView];

        //得到的是相对于子视图,点击坐标的位置

        //判断是否在子视图范围内,因为坐标是以各个子视图为原点的,然后判断这个子视图是否在这个坐标里面,因为它是以子视图为原点的

        BOOL result = [subView pointInside:subViewPoint withEvent:event];

        if (result) {

            //判断一些属性的值,来确定是否把事件分发到subView

            if (!subView.userInteractionEnabled) {//userInteractionEnabled该属性决定是否接受用户交互

                return [super hitTest:point withEvent:event];

            }

            

            

            return subView;

        }

    }

    

    return [super hitTest:point withEvent:event];


}


 




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值