手勢操作---識別單擊還是雙擊
在視圖上同時識別單擊手勢和雙擊手勢的問題在於,當檢測到一個單擊操作時,無法確定是確實是一個單擊操作或者只是雙擊操作中的第一次點擊。解決這個問題的方法就是:在檢測到單擊時,需要等一段時間等待第二次點擊,如果沒有第二次點擊,則為單擊操作;如果有第二次點擊,則為雙擊操作。
檢測手勢有兩種方法,一種是定制子視圖,重寫視圖從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