前段时间学习了IOS基础的一些控件的使用作为基础,现在开始学习一些高级编程的东西,手势处理器、文件I/O、定位、网络通信、多线程这些,分享一些学习的重点,还是很实用的。
今天就先介绍个简单点得,手势处理器:
一、首先,应该清楚ios事件相应的顺序,即响应者链。
只要继承了UIResponder的对象就可以作为响应者,实际上UIControl:UIView:UIResponder,由此可见,所有的对象都可以作为事件的相应者。
当用户与某个控件交互时,该控件将作为第一响应者(First Responder),第一响应者将作为响应链的开始,事件最先由控件本身处理,如果控件自身不处理,事件就会被传播到它对应的控制器(如果存在);如果视图控制器不处理,再向上传播到父控件,父控件不处理再传播到父控件的控制器,直到顶层视图对应的视图控制器。
如果事件从第一响应者到顶层视图的控制器都没有被处理,将会传播的应用程序窗口(UIWindow也继承了UIView),如果还不处理将会传播到UIApplication(:UIResponder),不处理会传播到应用程序的委托类中。
First Responder =》 First Responder的视图控制器(如果有) =》 父容器(如果有)=》父容器的视图控制器(如果有) =》 UIWindow =》 UIApplication =》 应用程序委托对象
如果在上面的流程中事件都没有被处理,那么事件就会被丢弃。一般来说,如果某一个环节处理了事件,那么事件就会停止传播;但是可以手动将事件继续向上传播。手动传递事件的方法:
-(void) handleTapEvent:(UIEvent *) event { if(condition) { //处理事件 } else { [self.nextResponder handleTapEvent:event];//手动传递事件 } }
(上面的流程有点类似于js的事件冒泡)
二、相应触碰的方法
如果希望在自定义控件中相应用户的触碰事件,则可以通过UIResponder的如下4个方法完成
- touchesBegan:(NSSet *)touches withEvent(UIEvent *) event: 当用户手指开始接触控件或窗口事件时激发
- touchesMoved:(NSSet *)touches withEvent(UIEvent *) event: 当用户手指在控件上移动时激发
- touchesEnded:(NSSet *)touches withEvent(UIEvent *) event: 当用户手指结束接触控件或窗口事件时激发
- touchesCancelled:(NSSet *)touches withEvent(UIEvent *) event: 当系统事件(比如内存低事件)终止了触碰事件时激发
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSInteger fingersNum = [touches count]; NSInteger tapCount = [[touches anyObject] tapCount]; NSLog(@"有%ld根手指点击了屏幕", (long)fingersNum); NSLog(@"手指点击了屏幕%ld次", (long)tapCount); }
UITouch对象代表一个触碰事件,touches即多个UITouch对象的集合,UITouch还提供了locationInView方法来获取该触碰事件在UIView控件中得触碰位置。
三、使用手势处理器(UIGestureRecognizer)
通过手势处理器处理手势将变得非常简单,无论处理那种手势,都可以面向UIGestureRecognizer编程,UIGestureRecognizer提供了下面几个子类:
UITapGestureRecognizer:处理用户点击手势
UIPinchGestureRecognizer:处理捏合手势
UIRotationGestureRecognizer:处理旋转手势
UISwipeGestureRecognizer:处理滑动手势
UIPanGestureRecognizer:处理拖动手势
UILongPressGestureRecognizer:处理长按手势
上面这几个类提供了IOS中几乎所有的手势处理。
使用手势处理器的步骤如下:
1、根据需要添加相应的手势处理器,指定处理器的target和action对象
2、如果该控件不允许用户交互,则将userInteractionEnabled设置为YES
3、调用UI控件的addGestureRecognizer方法添加手势处理器
UIGestureRecognizer提供了下面的常用方法和属性
locationInView:(UIView *) view 手势在view中的触碰位置
locationOfTouch:(NSInteger )touchIndex inView(UIView *) view 返回该手势中第touchindex个触碰点在view中得位置
numberOfTouches 触碰点得个数,即几个手指点击了屏幕
view 返回出发该手势的控件
enabled:用于设置和返回手势处理器是否可用
state:获取手势所处状态
下面使用UITapGestureRecognizer来处理点击手势,UIPinchGestureRecognizer处理捏合手势
1、实用storyboard设计界面,在界面拖入一个label和一个空得view,在view上绑定点击手势处理器,然后在label上显示我们对view做了些什么
#import <UIKit/UIKit.h> @interface TapEventSimpleController : UIViewController @property (weak, nonatomic) IBOutlet UILabel *lblText; @property (weak, nonatomic) IBOutlet UIView *viewContent; @end
import "TapEventSimpleController.h" @implementation TapEventSimpleController -(void)viewDidLoad { [super viewDidLoad]; //设置可以用户交互 self.viewContent.userInteractionEnabled = YES; //设置支持多点触碰 self.viewContent.multipleTouchEnabled = YES; for (int i = 1; i < 6; i++) { //创建手势处理器,制定该控制器的handleTap方法处理手势 UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]; //设置处理器只处理i次连击事件 gesture.numberOfTapsRequired = i; gesture.numberOfTouchesRequired = 2;//只处理2个手指的点击事件 [self.viewContent addGestureRecognizer:gesture]; } //创建捏合手势处理器 UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];
[self.viewContent addGestureRecognizer:pinchGesture]; } //tap处理方法 -(void)handleTap:(UITapGestureRecognizer *)gesture { //获取点击的手指 NSInteger touchNum = gesture.numberOfTouches; //获取点击的次数 NSInteger tapNum = gesture.numberOfTapsRequired; self.lblText.text = [NSString stringWithFormat:@"用户用%ld根手指点击了红色背景,点了%ld下",(long)touchNum,(long)tapNum]; //2秒后清除文本 //[self.lblText performSelector:@selector(setText:) withObject:nil afterDelay:2]; } //处理pinch方法 -(void)handlePinch:(UIPinchGestureRecognizer *) pinchGesture {//获取捏合的速度 CGFloat velocity = pinchGesture.velocity; CGFloat scale = pinchGesture.scale; self.lblPinchText.text = [NSString stringWithFormat:@"用户捏合的速度是:%g,捏合比例是%g",velocity,scale]; }
运行效果:
其他的几个手势处理器找时间再补充吧。