iOS开发中的几个手势操作实例分享
手势操作---识别单击还是双击
在视图上同时识别单击手势和双击手势的问题在于,当检测到一个单击操作时,无法确定是确实是一个单击操作或者只是双击操作中的第一次点击。解决这个问题的方法就是:在检测到单击时,需要等一段时间等待第二次点击,如果没有第二次点击,则为单击操作;如果有第二次点击,则为双击操作。
检测手势有两种方法,一种是定制子视图,重写视图从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