响应者链(面试常问)和手势(只是一些方法)
一、事件传递
1、从事件发生到其处理的对象,传递要经过特殊的一段过程,当用户点击设备屏幕时,iOS捕捉到一系列的触摸,将其打包到UIEvent对象并放置到应用程序活动事件队列中。
2、UIApplication对象从事件队列中取出最前面的事件并将其分发,通常,其将事件发送给应用程序的主窗口-UIWindow实例,再由窗口对象发送事件给第一响应者处理,一般通过touchesBegan方法获取该事件
3、具体过程
1)先将事件对象由上往下传递(由父控件传递给子控件),找到最合适的控件来处理这个事件 2)调用最合适控件的touches方法 3)如果调用了[super touches...]方法,就会将事件顺着"响应者链条"往上传递,传递给上一个响应者 4)接着就会调用上一个响应者的touches...方法
二、响应者链
1、基本概念
响应者对象是一个能接受并处理事件的对象,UIResponser是所有响应者对象的基类,该基类定义了一系列编程接口,不但为事件处理进行服务而且还提供了通用的响应行为处理,UIApplication、UIView(UIWindow)、UIViewController都直接或间接的继承自UIResponser,所有的这些类的实例都是响应者对象 响应者链表示一系列的响应者对象,事件被交由第一响应者对象处理,如果第一响应者不处理,事件被沿着响应者链向上传递,交给下一个响应者(nextresponder)
2、事件响应者链传递的过程(从下往上找)
1、当用户与试图交互时,会将消息传递给试图控制器,如果不存在控制器,传递给父试图 2、如果不处理该消息,则继续将消息向上传递,如果最上层的试图也不处理,将事件交给window对象,最后交由UIApplication实例,如果不处理,丢弃事件 PS:传递方式 [self.nextResponder touchesBegan:touches withEvent:event];
3、通过响应者链传递可以让多个试图响应同一个手势
四、手势识别器(在第五部分给大家具体的实例讲解)
UIGestureRecognizer类,用于检测、识别用户使用设备时所用的手势,他是一个抽象类,定义了所有手势的基本行为,以下是UIGestureRecognizer子类,用与处理具体的用户手势行为
1、轻击 UITapGestureRecognizer 常用属性 //点击次数 numberOfTapsRequired //消除两个手势的影响 requireGestureRecognizerToFail //手指的数量,需将试图的multipleTouchEnabled设为YES numberOfTouchesRequired 2、轻扫 UISwipeGestureRecognizer 常用属性 清扫方向,默认是右 direction 3、长按 UILongPressGestureRecognizer 常用属性 最小长按时间 minimumPressDuration 注意事项 如果不判断会调用2次 按下2秒后自己调用一次 松开后又要调用一次 if (longPress.state == UIGestureRecognizerStateEnded) { return; } NSLog(@"长按"); 4、平移 UIPanGestureRecognizer 常用方法 获取触摸的位置 locationInView 注意事项 - (void)panAction:(UIPanGestureRecognizer *)gesture{ // 1.在view上面挪动的距离 //translationInView表示相对于起点挪动的位置是最新2点之间的间距 CGPoint translation = [gesture translationInView:gesture.view]; CGPoint center = gesture.view.center; center.x += translation.x; center.y += translation.y; gesture.view.center = center; // 2.清空移动的距离 [gesture setTranslation:CGPointZero inView:gesture.view]; } 5、捏合 UIPinchGestureRecognizer 注意事项: 每次调用过方法后,记得将scale置1,否则你的图片在捏合一点便会变很大或很小 6、旋转 UIRotationGestureRecognizer 注意事项: 每次调用过方法后,记得将rotation置0,否则图片旋转不正常 7、手势识别器的代理方法 /** * 是否允许多个手势识别器同时有效 * Simultaneously : 同时地 */ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; } 8、重要的事情说三遍 实现旋转、缩放、平移的时候一定要清零 实现旋转、缩放、平移的时候一定要清零 实现旋转、缩放、平移的时候一定要清零
五、具体的实例讲解
#import "ViewController.h" @interface ViewController ()<UIGestureRecognizerDelegate> { UIImageView *imageView; } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; imageView = [[UIImageView alloc]initWithFrame:self.view.frame]; imageView.image = [UIImage imageNamed:@"minion"]; imageView.userInteractionEnabled = YES; [self.view addSubview:imageView]; #pragma mark 1.轻击 UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)]; tapGesture.numberOfTapsRequired = 1; [imageView addGestureRecognizer:tapGesture];//添加手势 #pragma mark 2.双击 UITapGestureRecognizer *doubleGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(doubleclick:)]; doubleGesture.numberOfTapsRequired = 2; [tapGesture requireGestureRecognizerToFail:doubleGesture]; //消除两个手势的影响 [imageView addGestureRecognizer:doubleGesture]; #pragma mark 3.两个手指同时点击 UITapGestureRecognizer *doubleTouchAndClick = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(doubleTouchAndClick:)]; doubleTouchAndClick.numberOfTouchesRequired = 2; doubleTouchAndClick.numberOfTapsRequired = 2; [imageView addGestureRecognizer:doubleTouchAndClick]; #pragma mark 4.清扫(就一个属性 direction) UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe)]; //设置清扫的对象 swipeGesture.direction = UISwipeGestureRecognizerDirectionDown; //添加手势 [imageView addGestureRecognizer:swipeGesture]; #pragma mark 5.长按 UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressGesture:)]; //长按的一个属性:长按最小时间 longPressGesture.minimumPressDuration = 2; [imageView addGestureRecognizer:longPressGesture]; #pragma mark 6.平移 UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panGesture:)]; [imageView addGestureRecognizer:panGesture]; #pragma mark 7.捏合 UIPinchGestureRecognizer *pinGesture = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinGesture:)]; pinGesture.delegate = self; [imageView addGestureRecognizer:pinGesture]; #pragma mark 8.旋转 UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotationGesture:)]; rotationGesture.delegate = self; [imageView addGestureRecognizer:rotationGesture]; } // 1.轻击 -(void)tap:(UITapGestureRecognizer *)gesture { NSLog(@"轻击"); } //2.双击 -(void)doubleclick:(UITapGestureRecognizer *)gesture { NSLog(@"双击"); } //3.两个手指同时点击 -(void)doubleTouchAndClick:(UITapGestureRecognizer *)gesture { NSLog(@"同时双击"); } //4.清扫 -(void)swipe { NSLog(@"清扫"); } //5.长按 -(void)longPressGesture:(UILongPressGestureRecognizer *)gesture { if (gesture.state == UIGestureRecognizerStateEnded) { return; } NSLog(@"长按"); } //6.平移 -(void)panGesture:(UIPanGestureRecognizer *)gesture { // 1.在view上面挪动的距离 //translationInView表示相对于起点挪动的位置是最新2点之间的间距 CGPoint translation = [gesture translationInView:gesture.view]; CGPoint center = gesture.view.center; center.x += translation.x; center.y += translation.y; gesture.view.center = center; // 2.清空移动的距离 [gesture setTranslation:CGPointZero inView:gesture.view]; } //7.捏合 -(void)pinGesture:(UIPinchGestureRecognizer *)gesture { imageView.transform = CGAffineTransformScale(imageView.transform, gesture.scale, gesture.scale); NSLog(@"%f",gesture.scale); gesture.scale = 1; } //8.旋转 - (void)rotationGesture:(UIRotationGestureRecognizer *)gesture { imageView.transform = CGAffineTransformRotate(imageView.transform, gesture.rotation); gesture.rotation = 0; } //9、手势识别器的代理方法 /** * 是否允许多个手势识别器同时有效 * Simultaneously : 同时地 */ - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; } @end