在视图上同时识别单击手势和双击手势的问题在于,当检测到一个单击操作时,无法确定是确实是一个单击操作或者只是双击操作中的第一次点击。解决这个问题的方法就是:在检测到单击时,需要等一段时间等待第二次点击,如果没有第二次点击,则为单击操作;如果有第二次点击,则为双击操作。
检测手势有两种方法,一种是定制子视图,重写视图从UIResponder类中继承来的事件处理方法,即touchesBegan:withEvent:等一系列方法来检测手势;另一个方法是使用手势识别器,即UIGestureRecognizer的各种具体子类。
一.重写事件处理方法
代码如下:
- (id)init {
if ((self = [super init])) {
self.userInteractionEnabled = YES;
self.multipleTouchEnabled = YES;
// ...
}
return self;
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
if (touch.tapCount == 1) {
[self performSelector:@selector(handleSingleTap:) withObject:[NSValue valueWithCGPoint:touchPoint] afterDelay:0.3];
}else if(touch.tapCount == 2)
{
[self handleDoubleTap:[NSValue valueWithCGPoint:touchPoint]];
}
}
-(void)handleSingleTap:(NSValue*)pointValue
{
CGPoint touchPoint = [pointValue CGPointValue];
//...
}
-(void)handleDoubleTap:(NSValue*)pointValue
{
CGPoint touchPoint = [pointValue CGPointValue];
//...
}
首先确认定制视图的userInteractionEnabled和multipleTouchEnabled属性都为YES.
在touchesEnded:withEvent:方法中,如果是第一次触摸结束,则cancelPreviousPerformRequestsWithTarget:方法不会起作用,因为self未调度任何方法,此时tapCount为1,使用performSelector:withObject:afterDelay:调用单击事件处理方法,在0.3s钟后执行。代码如下:
[self performSelector:@selector(handleSingleTap:) withObject:[NSValue valueWithCGPoint:touchPoint] afterDelay:0.3];
如果这是一个单击操作,则后面0.3钟内不会再有触摸事件,则handleSingleTap:方法执行,这样识别出了单击操作。
如果这是一个双击操作,则第二次点击在0.3s内触发,在第二次触摸操作的touchesEnded:withEvent:方法中,cancelPreviousPerformRequestsWithTarget:首先会取消之前对handleSingleTap:方法的调度,使之不会执行,然后在调用handleDoubleTap:方法处理双击操作。
二.使用Gesture Recognizer
使用Gesture Recognizer识别就会简单许多,只需添加两个手势识别器,分别检测单击和双击事件,设置必要的属性即可。
代码如下:
- (id)init {
if ((self = [super init])) {
self.userInteractionEnabled = YES;
UITapGestureRecognizer *singleTapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleSingleTap:)];
singleTapGesture.numberOfTapsRequired = 1;
singleTapGesture.numberOfTouchesRequired = 1;
[self addGestureRecognizer:singleTapGesture];
UITapGestureRecognizer *doubleTapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleDoubleTap:)];
doubleTapGesture.numberOfTapsRequired = 2;
doubleTapGesture.numberOfTouchesRequired = 1;
[self addGestureRecognizer:doubleTapGesture];
[singleTapGesture requireGestureRecognizerToFail:doubleTapGesture];
}
return self;
}
-(void)handleSingleTap:(UIGestureRecognizer *)sender{
CGPoint touchPoint = [sender locationInView:self];
//...
}
-(void)handleDoubleTap:(UIGestureRecognizer *)sender{
CGPoint touchPoint = [sender locationInView:self];
//...
}
唯一需要注意的是代码如下:
[singleTapGesture requireGestureRecognizerToFail:doubleTapGesture];
这句话的意思时,只有当doubleTapGesture识别失败的时候(即识别出这不是双击操作),singleTapGesture才能开始识别,同我们一开始讲的是同一个问题。
UIGestureRecognizer小应用
1、轻拍手势:双指、单击,修改imageView的frame为(0,0,320,200)
2、长按手指:单指,修改imageView的alpha=0.5
3、实现平移、旋转、捏合
4、轻扫:竖向轻扫实现图:像随机切换显示;横向轻扫实现:图像消失,随机修改imageview的背景颜色
5、imageview每次只能添加一种手势识别器。
代码如下:
#define _originalRect CGRectMake(10, 50, 300, 450)
#define _originalImageName @"h4.jpeg"
#import "HMTRootViewController.h"
@interface HMTRootViewController (){
UITapGestureRecognizer * _tapGesture;
UILongPressGestureRecognizer * _longGesture;
UIPanGestureRecognizer * _panGesture;
UIRotationGestureRecognizer * _rotateGesture;
UIPinchGestureRecognizer * _pinchGesture;
UISwipeGestureRecognizer * _verticalSwipeGesture;
UISwipeGestureRecognizer * _horizontanlSwipeGesture;
BOOL isTopDownOfRightLeft; // 垂直滑动是YES,水平滑动是NO
}
@property (nonatomic,retain) UIButton * button;
@property (nonatomic,retain) UIImageView * imageView;
@end
@implementation HMTRootViewController
- (void)dealloc{
RELEASE_SAFELY(_imageView);
RELEASE_SAFELY(_button);
[super dealloc];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
isTopDownOfRightLeft = YES;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self createButtonView];
[self createImageView];
}
#pragma mark - 设置图像
- (void)createImageView{
self.imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:_originalImageName]];
_imageView.frame = CGRectMake(10, 50, 300, 450);
_imageView.userInteractionEnabled = YES;
[self.view addSubview:_imageView];
[_imageView release];
}
#pragma mark - 设置手势
#pragma mark 点击手势
- (void)createTapGestureRecognizer{
_tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(TapGestureRecognizer:)];
_tapGesture.numberOfTapsRequired = 1;
_tapGesture.numberOfTouchesRequired = 2;
[self.imageView addGestureRecognizer:_tapGesture];
[_tapGesture release];
}
- (void)TapGestureRecognizer:(UITapGestureRecognizer *)tapGesture{
self.imageView.frame = CGRectMake(0, 0, 320, 200);
NSLog(@"%@",NSStringFromCGRect(self.imageView.frame));
}
#pragma mark 长按手势
- (void)createLongGestureRecognizer{
_longGesture = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longGestureRecognizer:)];
_longGesture.numberOfTouchesRequired = 1;
_longGesture.minimumPressDuration = 1.0;
[self.imageView addGestureRecognizer:_longGesture];
[_longGesture release];
}
- (void)longGestureRecognizer:(UILongPressGestureRecognizer *)longGesture{
self.imageView.alpha = 0.5;
NSLog(@"%s",__FUNCTION__);
}
#pragma mark 平移拖拽手势
- (void)createPanGestureRecognizer{
_panGesture = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panGestureRecognizer:)];
[self.imageView addGestureRecognizer:_panGesture];
[_panGesture release];
}
- (void)panGestureRecognizer:(UIPanGestureRecognizer *)panGesture{
NSLog(@"%s",__FUNCTION__);
CGPoint txty = [panGesture translationInView:self.view];
self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, txty.x, txty.y);
[panGesture setTranslation:CGPointMake(0, 0) inView:self.view];
}
#pragma mark 旋转手势
- (void)createRotationGestureRecognizer{
_rotateGesture = [[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotationGestureRecognizer:)];
[self.imageView addGestureRecognizer:_rotateGesture];
[_rotateGesture release];
}
- (void)rotationGestureRecognizer:(UIRotationGestureRecognizer *)rotateGesture{
NSLog(@"%s",__FUNCTION__);
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, rotateGesture.rotation);
rotateGesture.rotation = 0;
}
#pragma mark 捏合缩放手势
- (void)createPinchGestureRecognizer{
_pinchGesture = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinchGestureRecognizer:)];
[self.imageView addGestureRecognizer:_pinchGesture];
[_pinchGesture release];
}
- (void)pinchGestureRecognizer:(UIPinchGestureRecognizer *)pinchGesture{
NSLog(@"%s",__FUNCTION__);
self.imageView.transform = CGAffineTransformScale(self.imageView.transform, pinchGesture.scale, pinchGesture.scale);
pinchGesture.scale = 1;
}
#pragma mark - 轻扫手势
#pragma mark 上下 竖 垂直轻扫
- (void)createVerticalSwipeGestureRecognizer{
_verticalSwipeGesture = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeGestureRecognizer:)];
_verticalSwipeGesture.direction = UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown;
[self.imageView addGestureRecognizer:_verticalSwipeGesture];
[_verticalSwipeGesture release];
}
#pragma mark 水平 左右轻扫
- (void)createHorizontanlSwipeGesture{
_horizontanlSwipeGesture = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipeGestureRecognizer:)];
_horizontanlSwipeGesture.direction = UISwipeGestureRecognizerDirectionLeft |UISwipeGestureRecognizerDirectionRight;
[self.imageView addGestureRecognizer:_horizontanlSwipeGesture];
}
- (void)swipeGestureRecognizer:(UISwipeGestureRecognizer *)swipeGesture{
NSLog(@"%s",__FUNCTION__);
if (swipeGesture.direction == (UISwipeGestureRecognizerDirectionUp|UISwipeGestureRecognizerDirectionDown)) {
self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"h%i.jpeg",arc4random()%7+1]];
;
}else if (swipeGesture.direction == (UISwipeGestureRecognizerDirectionLeft|UISwipeGestureRecognizerDirectionRight)){
self.imageView.image = nil;
self.imageView.backgroundColor = [UIColor colorWithRed:arc4random()%256/255.0 green:arc4random()%256/255.0 blue:arc4random()%256/255.0 alpha:1.0];
}
}
#pragma mark - 设置按钮
- (void)createButtonView{
NSArray * buttonArray = @[@"轻点",@"长按",@"平移",@"旋转",@"捏合",@"轻扫"];
for (int i = 0; i [buttonArray count]; i++) {
self.button = [UIButton buttonWithType:UIButtonTypeSystem];
_button.frame = CGRectMake(10+50*i, 500, 50, 48);
[_button setTitle:[buttonArray objectAtIndex:i] forState:UIControlStateNormal];
[_button addTarget:self action:@selector(onClikButton:) forControlEvents:UIControlEventTouchUpInside];
_button.tag = i;
[self.view addSubview:_button];
}
}
- (void)onClikButton:(UIButton *)button{
[self resetImageView];
switch (button.tag) {
case 0:
[self createTapGestureRecognizer];
break;
case 1:
[self createLongGestureRecognizer];
break;
case 2:
[self createPanGestureRecognizer];
break;
case 3:
[self createRotationGestureRecognizer];
break;
case 4:
[self createPinchGestureRecognizer];
break;
case 5:
if (isTopDownOfRightLeft == YES) {
[self createVerticalSwipeGestureRecognizer];
isTopDownOfRightLeft = NO;
} else {
[self createHorizontanlSwipeGesture];
isTopDownOfRightLeft = YES;
}
break;
default:
break;
}
}
#pragma mark - 重置imageView
- (void)resetImageView
{
for (int i = 0; i [self.imageView.gestureRecognizers count]; i++) {
[self.imageView removeGestureRecognizer:[self.imageView.gestureRecognizers objectAtIndex:i]];
}
self.imageView.alpha = 1.0;
self.imageView.transform = CGAffineTransformIdentity;
self.imageView.frame = _originalRect;
self.imageView.image = [UIImage imageNamed:_originalImageName];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end