您的位置:首页 > 移动开发 > IOS开发

iOS 触摸事件五:手势处理器

2015-12-25 16:44 330 查看
通过touches方法监听触摸事件,不容易区分用户的具体手势行为。为此,苹果推出了手势处理器(UIGestureRecognizer)。手势处理器处理用户触摸事件更加简单,而且无论处理哪种触摸手势,都可以面向GestureRecognizer编程。个人认为手势处理器即为手势触摸四个方法的一种封装。

平时我们使用手势处理器一般不直接使用UIGestureRecognizer,而是使用UIGesturerecognizer提供的六大子类来处理具体的手势:

- UITapGestureRecognizer: 处理用户点击手势的手势处理器

- UIPinchGestureRecognizer: 处理用户捏合手势的手势处理器

- UIPanGestureRecognizer: 处理用户拖拽手势的手势处理器

- UISwipeGestureRecognizer: 处理用户轻扫手势的手势处理器

- UIRotationGestureRecognizer: 处理用户旋转手势的手势处理器

手势处理器的处理用户触摸手势的步骤:

根据程序要处理的手势创建对应的手势处理器对象。创建手势处理器时需要指定target和action参数(当该控件上发生触摸手势后,该Target对象的action方法将会被激发,即目标-行为模式)

如果该UI控件不允许用户交互,则将该UI控件的userInteractionEnabled的属性设置为YES; 如果希望该空间可支持多点触摸,还需要将mutipleTouchEnable(是否多点触摸)设置为YES

调用该UI控件的addGestureRecognizer:方法添加该手势处理器

UIGestureRecognizer提供的一些常用方法和属性:

UIGestureRecognizer作为所有手势处理器的基类,提供了一些常用的方法和属性:
- (CGPoint)locationInView:(UIView*)view; //返回该手势在view控件中的触摸位置
- (NSUInteger)numberOfTouches;   // 返回该手势包含触摸点的数量(就是用户用了几个手指进行触摸)
- view:  返回激发该收拾的UI控件
- enabled: 用于设置和返回该手势处理器是否可用
- state:  只读,获取该收拾的状态,(枚举值)比如
手势刚刚开始处于UIGestureRecognizerStateBegan状态
手势改变时处于UIGestureRecognizerStateChanged状态
手势结束时处于UIGestureRecognizerStateEnded状态


UITapGestureRecognizer:

点击手势的手势处理器,继承了UIGEstureRecognizer类,除了拥有父类的属性方法外,还提供了如下的两个属性:
numberOfTapsRequired: 指定该手势处理器只处理几次触摸事件,默认是1
numberOfTouchesRequired: 指定该手势处理器只能处理几个手指触摸事件,默认是1
使用:
1. 创建Tap手势


UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selecor(handlePanGesture:)];
//对手势进行初始化,并指定出发该手势时的所出发(调用)的handlePanGesture:方法。 同时会传递一个UIPanGestureRecognizer类型的参数


2. 对手势的设置(可选)


tapGesture.numberOfTouchesRequired = 1;//设置手势需要的触点的数量
tapGesture.numberOfTapsRequired = 1; //设置手势需要点击的次数


3. 将手势添加到UI控件上


//调用UIView的addGestureRecognizer:方法即可
[self.view addGestureRecognizer:tapGesture];

//手势触发时调用的方法
-(void)handlePanGesture:(UIPanGestureRecognizer *)gesture{
NSLog(@"点击手势");
}


UIPinchGestureRecognizer:

捏合手势,同样继承了UIRespond类,使用步骤和点击手势处理器完全相同,额外增加了两个属性来获取相关信息:
scale :获取捏合的比例
velocity : 获取捏合的速度
捏合手势一般用于图片的缩放。处理是要设置一下,避免缩放的速度过快。
使用:


//打开imgView的交互
_imgView.userInteractionEnabled = YES;
//打开imgView多点触摸 ,前提,多触点事件,要打开控件的多点触摸
_imgView.multipleTouchEnabled = YES;
//创建手势, target-action
UIPinchGestureRecognizer *gesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];

//为imgView添加手势
[_imgView addGestureRecognizer:gesture];
}

//手势处理函数
-(void)handlePinch:(UIPinchGestureRecognizer *)gesture{
//手势处理
NSLog(@"缩放。。");
//获取捏合的比例
CGFloat scale = gesture.scale;
//直接缩放
// _imgView.transform = CGAffineTransformMakeScale(scale, scale);  //--第二次缩放时回到原来
//相对某个tranform进行缩放-- 在原有的基础上进行缩放
_imgView.transform = CGAffineTransformScale(_imgView.transform, scale, scale) ;//--缩放的速度太快
//优化。让缩放比例变为1,避免缩放过快
gesture.scale = 1.0f;
}


UIPanGestureRecognizer:

拖拽手势, 该手势设置相关信息的属性:
maximumNumberOfTouches: 设置该手势处理器最多支持几个手指拖动
minimumNumberOfTouches: 设置该手势处理器最少需要几个手指拖动
translationInView: 获取拖动手势在指定控件上的位移。该方法返回一个CGPoint类型,该结构体中的x值代表水平方向的位移,y的值代表垂直方向上的位移
velocityInView: 获取该拖动手势在指定控件上的拖动速度,该方法返回一个CGPoint类型,该结构体中的x值代表水平方向的移动速度,y的值代表垂直方向上的移动速度
`
- (void)viewDidLoad {
[super viewDidLoad];

UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleAction:)];

pan.maximumNumberOfTouches = 3; //设置手势最多支持3个手指触点
pan.minimumNumberOfTouches = 1; //设置手势至少1个手指触点

[_imgView addGestureRecognizer:pan];


}

-(void)handleAction:(UIPanGestureRecognizer *)gesture{

CGPoint offSet = [gesture translationInView:_imgView];

//判断边界

_imgView.transform = CGAffineTransformTranslate(_imgView.transform, offSet.x, offSet.y);
[gesture setTranslation:CGPointMake(0,0) inView:_imgView];


}

`


UISwipeGestureRecognizer:

轻扫手势,获取与轻扫相关的信息:
numberOfTouchesRequired: 设置该手势只处理几个手指的触摸事件
direction: 设置该手势处理器只处理某个方向的轻扫,该属性支持上、下、左、右4个枚举值,一个手势处理器只能设置一个方向
示例         `- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.

imgView = [[UIImageView alloc] initWithFrame:CGRectMake(SCREEN.size.width/2-32, SCREEN.size.height/2-32, 32,32)];
imgView.image = [UIImage imageNamed:@"a0_.9.png"];

UISwipeGestureRecognizer *swip = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleAction:)];
swip.numberOfTouchesRequired = 1; //需要一个触点
swip.direction = UISwipeGestureRecognizerDirectionUp;

UISwipeGestureRecognizer *swip1 = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleAction:)];
swip1.numberOfTouchesRequired = 1; //需要一个触点
swip1.direction = UISwipeGestureRecognizerDirectionRight;

UISwipeGestureRecognizer *swip2 = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleAction:)];
swip2.numberOfTouchesRequired = 1; //需要一个触点
swip2.direction = UISwipeGestureRecognizerDirectionDown;

UISwipeGestureRecognizer *swip3 = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleAction:)];
swip3.numberOfTouchesRequired = 1; //需要一个触点
swip3.direction = UISwipeGestureRecognizerDirectionLeft;

[self.view addSubview:imgView];
[self.view addGestureRecognizer:swip];
[self.view addGestureRecognizer:swip1];
[self.view addGestureRecognizer:swip2];
[self.view addGestureRecognizer:swip3];


}

-(void)handleAction:(UISwipeGestureRecognizer *)gesture{

CGRect rect = imgView.frame;
NSLog(@"rect.x = %.2f, rect.y = %.2f", rect.origin.x, rect.origin.y);
if(gesture.direction == UISwipeGestureRecognizerDirectionUp ){
//向上
NSLog(@"向上");
if(rect.origin.y >= 120){
rect.origin.y -= 20;
}else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"到头了啊" delegate:nil cancelButtonTitle:@"是" otherButtonTitles: nil];
[alert show];
}
}
if(gesture.direction == UISwipeGestureRecognizerDirectionRight){
//向右
NSLog(@"向右");
if(rect.origin.x+32 <= 270){
rect.origin.x += 20;
}else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"到头了啊" delegate:nil cancelButtonTitle:@"是" otherButtonTitles: nil];
[alert show];
}

}
if(gesture.direction == UISwipeGestureRecognizerDirectionDown){
//向下
NSLog(@"向下");
if(rect.origin.y+32 <= 500){
rect.origin.y += 20;
}else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"到头了啊" delegate:nil cancelButtonTitle:@"是" otherButtonTitles: nil];
[alert show];
}

}
if(gesture.direction == UISwipeGestureRecognizerDirectionLeft){
//向左
NSLog(@"向左");
if(rect.origin.x >= 20){
rect.origin.x -= 20;
}else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"到头了啊" delegate:nil cancelButtonTitle:@"是" otherButtonTitles: nil];
[alert show];
}

}
imgView.frame = rect;


}`

UIRotationGestureRecognizer:

旋转手势,额外定义了2个属性来获取旋转的相关信息:
rotation: 获取旋转的角度
velocity: 获取旋转的速度
旋转手势同样经常用于图片的旋转处理,同样优化一下,避免旋转过快
使用与上类似:


- (void)viewDidLoad {
[super viewDidLoad];

UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotation:)];

_imgView.userInteractionEnabled = YES;           _imgView.multipleTouchEnabled   = YES;

[_imgView addGestureRecognizer:rotation];
}

-(void)handleRotation:(UIRotationGestureRecognizer *)gesture{
NSLog(@"旋转");
//获取旋转的角度
CGFloat rotation = gesture.rotation;

//对图片进行旋转
_imgView.transform = CGAffineTransformRotate(_imgView.transform, rotation);

//优化,避免旋转过快
gesture.rotation = 0.0f;

}


UILongPressGestureRecognizer:

长按手势,设置相关信息的属性:

minmumPressDuration: 指定用户至少在屏幕上按下多少秒才会触发长按手势,默认值是0.5秒

allowableMovement:指定该长按手势允许用户移动手指的最大距离。如果用户手指按下时的移动距离超过了该距离,则长按手势失效

numberOfTouchesRequired: 指定必须使用几个手指在屏幕上长按才会触发该手势

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.

//定义3个自定义的菜单项
transmitItem = [[UIMenuItem alloc] initWithTitle:@"转发" action:@selector(transmitClick:)];
deleteItem = [[UIMenuItem alloc] initWithTitle:@"删除" action:@selector(deleteClick:)];
reportItem = [[UIMenuItem alloc] initWithTitle:@"举报" action:@selector(reportClick:)];

//创建手势处理器,指定该控制器使用的行为方法
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressAction:)];
_imgView.userInteractionEnabled = YES;
//为视图添加手势
[_imgView addGestureRecognizer:longPressGesture];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

/*自定义菜单项的点击事件*/
-(void)transmitClick:(id)sender{
NSLog(@"点击转发");
}
-(void)deleteClick:(id)sender{
NSLog(@"点击删除");
}
-(void)reportClick:(id)sender{
NSLog(@"点击举报");
}
/*end*/

/*手势处理器的action函数, 当该方法被激活时,手势处理器会作为参数传递给该方法的参数*/
-(void)handleLongPressAction:(UILongPressGestureRecognizer *)gesture{
//"开始触摸状态"时进入
if(gesture.state == UIGestureRecognizerStateBegan){
NSLog(@"长按手势触发");
[self becomeFirstResponder];
//创建一个menu控制器
UIMenuController *menu = [UIMenuController sharedMenuController];
menu.menuItems = @[transmitItem, deleteItem, reportItem];

//悬浮在哪一个view上(定位Menu)并确定其大小
CGRect rect = CGRectMake(0, 0, 100, 50);
[menu setTargetRect:rect inView:_imgView];

//展示Menu
[menu setMenuVisible:YES];
}
}
/*end*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: