在 iPhone 或 iPad 的開發(fā)中烟阐,除了用 touchesBegan / touchesMoved / touchesEnded 這組方法來控制使用者的手指觸控外偎快,也可以用 UIGestureRecognizer 的衍生類別來進(jìn)行判斷岗屏。用 UIGestureRecognizer 的好處在于有現(xiàn)成的手勢(shì),開發(fā)者不用自己計(jì)算手指移動(dòng)軌跡。UIGestureRecognizer的衍生類別有以下幾種:
UITapGestureRecognizer
UIPinchGestureRecognizer
UIRotationGestureRecognizer
UISwipeGestureRecognizer
UIPanGestureRecognizer
UILongPressGestureRecognizer
從命名上不難了解這些類別所對(duì)應(yīng)代表的手勢(shì)布近,分別是 Tap(點(diǎn)一下)因惭、Pinch(二指往內(nèi)或往外撥動(dòng))岳锁、Rotation(旋轉(zhuǎn))、Swipe(滑動(dòng)蹦魔,快速移動(dòng))激率、Pan (拖移,慢速移動(dòng))以及 LongPress(長(zhǎng)按)勿决。這些手勢(shì)別在使用上也很簡(jiǎn)單乒躺,只要在使用前定義并添加到對(duì)應(yīng)的視圖上即可。
The concrete subclasses of UIGestureRecognizer
are the following:
UITapGestureRecognizer
一個(gè)gesture recognizer是針對(duì)一個(gè)特定的view的(包含其subview)低缩,用UIView的方法addGestureRecognize:去關(guān)聯(lián)一個(gè)view
一個(gè)gesture recognizer是不參與UIView的事件響應(yīng)鏈的
各個(gè)手勢(shì)使用時(shí)的代碼:
UITapGestureRecognizer
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
if (![tapGesture respondsToSelector:@selector(locationInView:)]) {
[tapGesture release];
tapGesture = nil;
}else {
tapGesture.delegate = self;
tapGesture.numberOfTapsRequired = 1; // The default value is 1.
tapGesture.numberOfTouchesRequired = 1; // The default value is 1.
[self.view addGestureRecognizer:tapGesture];
}
}
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
{
UIView *view = [gestureRecognizer view]; // 這個(gè)view是手勢(shì)所屬的view嘉冒,也就是增加手勢(shì)的那個(gè)view
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateEnded:{ // UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded // 正常情況下只響應(yīng)這個(gè)消息
NSLog(@"======UIGestureRecognizerStateEnded || UIGestureRecognizerStateRecognized");
break;
}
case UIGestureRecognizerStateFailed:{ //
NSLog(@"======UIGestureRecognizerStateFailed");
break;
}
case UIGestureRecognizerStatePossible:{ //
NSLog(@"======UIGestureRecognizerStatePossible");
break;
}
default:{
NSLog(@"======Unknow gestureRecognizer");
break;
}
}
}
// 詢問一個(gè)手勢(shì)接收者是否應(yīng)該開始解釋執(zhí)行一個(gè)觸摸接收事件
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
// CGPoint currentPoint = [gestureRecognizer locationInView:self.view];
// if (CGRectContainsPoint(CGRectMake(0, 0, 100, 100), currentPoint) ) {
// return YES;
// }
//
// return NO;
return YES;
}
// 詢問delegate,兩個(gè)手勢(shì)是否同時(shí)接收消息咆繁,返回YES同事接收讳推。返回NO,不同是接收(如果另外一個(gè)手勢(shì)返回YES玩般,則并不能保證不同時(shí)接收消息)the default implementation returns NO银觅。
// 這個(gè)函數(shù)一般在一個(gè)手勢(shì)接收者要阻止另外一個(gè)手勢(shì)接收自己的消息的時(shí)候調(diào)用
-
(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return NO;
}
// 詢問delegate是否允許手勢(shì)接收者接收一個(gè)touch對(duì)象
// 返回YES,則允許對(duì)這個(gè)touch對(duì)象審核坏为,NO究驴,則不允許。
// 這個(gè)方法在touchesBegan:withEvent:之前調(diào)用匀伏,為一個(gè)新的touch對(duì)象進(jìn)行調(diào)用
-
(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
return YES;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
if (![pinchGesture respondsToSelector:@selector(locationInView:)]) {
[pinchGesture release];
pinchGesture = nil;
}else {
pinchGesture.delegate = self;
[self.view addGestureRecognizer: pinchGesture];
}
}
- (void)handleGesture:(UIPinchGestureRecognizer *)gestureRecognizer
{
UIView *view = [gestureRecognizer view]; // 這個(gè)view是手勢(shì)所屬的view洒忧,也就是增加手勢(shì)的那個(gè)view
CGFloat scale = gestureRecognizer.scale;
NSLog(@"======scale: %f", scale);
CGFloat velocity = gestureRecognizer.velocity;
NSLog(@"======scvelocityale: %f", velocity);
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateEnded:{ // UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded
NSLog(@"======UIGestureRecognizerStateEnded || UIGestureRecognizerStateRecognized");
break;
}
case UIGestureRecognizerStateBegan:{ //
NSLog(@"======UIGestureRecognizerStateBegan");
break;
}
case UIGestureRecognizerStateChanged:{ //
NSLog(@"======UIGestureRecognizerStateChanged");
gestureRecognizer.view.transform = CGAffineTransformScale(gestureRecognizer.view.transform, gestureRecognizer.scale, gestureRecognizer.scale);
gestureRecognizer.scale = 1; // 重置,很重要9坏摺N跏獭!
break;
}
case UIGestureRecognizerStateCancelled:{ //
NSLog(@"======UIGestureRecognizerStateCancelled");
break;
}
case UIGestureRecognizerStateFailed:{ //
NSLog(@"======UIGestureRecognizerStateFailed");
break;
}
case UIGestureRecognizerStatePossible:{ //
NSLog(@"======UIGestureRecognizerStatePossible");
break;
}
default:{
NSLog(@"======Unknow gestureRecognizer");
break;
}
}
}
recognizer.scale是pinch手勢(shì)的scale值,它每次都是從1開始蛉抓,以兩指的距離為參考牢硅,如果捏合兩指,則scale變兄パ减余;如果兩指向外拉,則scale變大
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
if (![rotationGesture respondsToSelector:@selector(locationInView:)]) {
[rotationGesture release];
rotationGesture = nil;
}else {
rotationGesture.delegate = self;
[self.view addGestureRecognizer:rotationGesture];
}
}
- (void)handleGesture:(UIRotationGestureRecognizer *)gestureRecognizer
{
UIView *view = [gestureRecognizer view]; // 這個(gè)view是手勢(shì)所屬的view惩系,也就是增加手勢(shì)的那個(gè)view
CGFloat rotation = gestureRecognizer.rotation;
NSLog(@"===rotation: %f", rotation);
CGFloat velocity = gestureRecognizer.velocity;
NSLog(@"======velocity: %f", velocity);
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateEnded:{ // UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded
NSLog(@"======UIGestureRecognizerStateEnded || UIGestureRecognizerStateRecognized");
break;
}
case UIGestureRecognizerStateBegan:{ //
NSLog(@"======UIGestureRecognizerStateBegan");
break;
}
case UIGestureRecognizerStateChanged:{ //
NSLog(@"======UIGestureRecognizerStateChanged");
gestureRecognizer.view.transform = CGAffineTransformRotate(gestureRecognizer.view.transform, gestureRecognizer.rotation);
gestureRecognizer.rotation = 0; // 重置 這個(gè)相當(dāng)重要N徊怼!堡牡!
break;
}
case UIGestureRecognizerStateCancelled:{ //
NSLog(@"======UIGestureRecognizerStateCancelled");
break;
}
case UIGestureRecognizerStateFailed:{ //
NSLog(@"======UIGestureRecognizerStateFailed");
break;
}
case UIGestureRecognizerStatePossible:{ //
NSLog(@"======UIGestureRecognizerStatePossible");
break;
}
default:{
NSLog(@"======Unknow gestureRecognizer");
break;
}
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// right
UISwipeGestureRecognizer *swipeGestureRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
if (![swipeGestureRight respondsToSelector:@selector(locationInView:)]) {
[swipeGestureRight release];
swipeGestureRight = nil;
}else {
swipeGestureRight.delegate = self;
swipeGestureRight.numberOfTouchesRequired = 1;// 手指?jìng)€(gè)數(shù) The default value is 1.
swipeGestureRight.direction = UISwipeGestureRecognizerDirectionRight;// 同一個(gè)手勢(shì)只能指定一個(gè)方向抒抬,不能同時(shí)指定多個(gè)方向,要指定多個(gè)方向 必須用多個(gè)手勢(shì)
[self.view addGestureRecognizer:swipeGestureRight];
}
// left
UISwipeGestureRecognizer *swipeGestureLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
if (![swipeGestureLeft respondsToSelector:@selector(locationInView:)]) {
[swipeGestureLeft release];
swipeGestureLeft = nil;
}else {
swipeGestureLeft.delegate = self;
swipeGestureLeft.numberOfTouchesRequired = 1;// 手指?jìng)€(gè)數(shù) The default value is 1.
swipeGestureLeft.direction = UISwipeGestureRecognizerDirectionLeft;// 同一個(gè)手勢(shì)只能指定一個(gè)方向晤柄,不能同時(shí)指定多個(gè)方向擦剑,要指定多個(gè)方向 必須用多個(gè)手勢(shì)
[self.view addGestureRecognizer:swipeGestureLeft];
}
// Up
UISwipeGestureRecognizer *swipeGestureUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
if (![swipeGestureUp respondsToSelector:@selector(locationInView:)]) {
[swipeGestureUp release];
swipeGestureUp = nil;
}else {
swipeGestureUp.delegate = self;
swipeGestureUp.numberOfTouchesRequired = 1;// 手指?jìng)€(gè)數(shù) The default value is 1.
swipeGestureUp.direction = UISwipeGestureRecognizerDirectionUp;// 同一個(gè)手勢(shì)只能指定一個(gè)方向,不能同時(shí)指定多個(gè)方向芥颈,要指定多個(gè)方向 必須用多個(gè)手勢(shì)
[self.view addGestureRecognizer:swipeGestureUp];
}
// Down
UISwipeGestureRecognizer *swipeGestureDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
if (![swipeGestureDown respondsToSelector:@selector(locationInView:)]) {
[swipeGestureDown release];
swipeGestureDown = nil;
}else {
swipeGestureDown.delegate = self;
swipeGestureDown.numberOfTouchesRequired = 1;// 手指?jìng)€(gè)數(shù) The default value is 1.
swipeGestureDown.direction = UISwipeGestureRecognizerDirectionDown;// 同一個(gè)手勢(shì)只能指定一個(gè)方向惠勒,不能同時(shí)指定多個(gè)方向,要指定多個(gè)方向 必須用多個(gè)手勢(shì)
[self.view addGestureRecognizer:swipeGestureDown];
}
}
- (void)handleGesture:(UISwipeGestureRecognizer *)gestureRecognizer
{
UIView *view = [gestureRecognizer view]; // 這個(gè)view是手勢(shì)所屬的view爬坑,也就是增加手勢(shì)的那個(gè)view
UISwipeGestureRecognizerDirection direction = gestureRecognizer.direction;
switch (direction) {
case UISwipeGestureRecognizerDirectionRight:
{
NSLog(@"direction==UISwipeGestureRecognizerDirectionRight");
break;
}
case UISwipeGestureRecognizerDirectionLeft:
{
NSLog(@"direction==UISwipeGestureRecognizerDirectionLeft");
break;
}
case UISwipeGestureRecognizerDirectionUp:
{
NSLog(@"direction==UISwipeGestureRecognizerDirectionUp");
break;
}
case UISwipeGestureRecognizerDirectionDown:
{
NSLog(@"direction==UISwipeGestureRecognizerDirectionDown");
break;
}
default:
break;
}
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateEnded:{ // UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded
NSLog(@"======UIGestureRecognizerStateEnded || UIGestureRecognizerStateRecognized");
break;
}
default:{
NSLog(@"======Unknow gestureRecognizer");
break;
}
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
view.backgroundColor = [UIColor blueColor];
[self.view addSubview:view];
UIPanGestureRecognizer *panPressGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
if (![panPressGesture respondsToSelector:@selector(locationInView:)]) {
[panPressGesture release];
panPressGesture = nil;
}else {
panPressGesture.delegate = self;
panPressGesture.maximumNumberOfTouches = NSUIntegerMax;// The default value is NSUIntegerMax.
panPressGesture.minimumNumberOfTouches = 1;// The default value is 1.
[view addGestureRecognizer:panPressGesture];
}
}
// 拖拽手勢(shì)
- (void)handleGesture:(UIPanGestureRecognizer *)gestureRecognizer
{
UIView *view = [gestureRecognizer view]; // 這個(gè)view是手勢(shì)所屬的view纠屋,也就是增加手勢(shì)的那個(gè)view
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateBegan:{
NSLog(@"======UIGestureRecognizerStateBegan");
break;
}
case UIGestureRecognizerStateChanged:{
NSLog(@"======UIGestureRecognizerStateChanged");
CGPoint translation = [gestureRecognizer translationInView:self.view];
view.center = CGPointMake(gestureRecognizer.view.center.x + translation.x, gestureRecognizer.view.center.y + translation.y);
[gestureRecognizer setTranslation:CGPointMake(0, 0) inView:self.view];// 注意一旦你完成上述的移動(dòng),將translation重置為0十分重要盾计。否則translation每次都會(huì)疊加售担,很快你的view就會(huì)移除屏幕!
break;
}
case UIGestureRecognizerStateCancelled:{
NSLog(@"======UIGestureRecognizerStateCancelled");
break;
}
case UIGestureRecognizerStateFailed:{
NSLog(@"======UIGestureRecognizerStateFailed");
break;
}
case UIGestureRecognizerStatePossible:{
NSLog(@"======UIGestureRecognizerStatePossible");
break;
}
case UIGestureRecognizerStateEnded:{ // UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded
NSLog(@"======UIGestureRecognizerStateEnded || UIGestureRecognizerStateRecognized");
CGPoint velocity = [gestureRecognizer velocityInView:self.view];// 分別得出x署辉,y軸方向的速度向量長(zhǎng)度(velocity代表按照當(dāng)前速度族铆,每秒可移動(dòng)的像素個(gè)數(shù),分xy軸兩個(gè)方向)
CGFloat magnitude = sqrtf((velocity.x * velocity.x) + (velocity.y * velocity.y));// 根據(jù)直角三角形的算法算出綜合速度向量長(zhǎng)度
// 如果長(zhǎng)度小于200哭尝,則減少基本速度哥攘,否則增加它。
CGFloat slideMult = magnitude / 200;
NSLog(@"magnitude: %f, slideMult: %f", magnitude, slideMult);
float slideFactor = 0.1 * slideMult; // Increase for more of a slide
// 基于速度和滑動(dòng)因子計(jì)算終點(diǎn)
CGPoint finalPoint = CGPointMake(view.center.x + (velocity.x * slideFactor),
view.center.y + (velocity.y * slideFactor));
// 確定終點(diǎn)在視圖邊界內(nèi)
finalPoint.x = MIN(MAX(finalPoint.x, 0), self.view.bounds.size.width);
finalPoint.y = MIN(MAX(finalPoint.y, 0), self.view.bounds.size.height);
[UIView animateWithDuration:slideFactor*2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
view.center = finalPoint;
} completion:nil];
break;
}
default:{
NSLog(@"======Unknow gestureRecognizer");
break;
}
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleGesture:)];
if (![longPressGesture respondsToSelector:@selector(locationInView:)]) {
[longPressGesture release];
longPressGesture = nil;
}else {
longPressGesture.delegate = self;
longPressGesture.numberOfTapsRequired = 0; // The default number of taps is 0.
longPressGesture.minimumPressDuration = 0.1f; // The default duration is is 0.5 seconds.
longPressGesture.numberOfTouchesRequired = 1; // The default number of fingers is 1.
longPressGesture.allowableMovement = 10; // The default distance is 10 pixels.
[self.view addGestureRecognizer:longPressGesture];
}
}
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
{
UIView *view = [gestureRecognizer view]; // 這個(gè)view是手勢(shì)所屬的view刚夺,也就是增加手勢(shì)的那個(gè)view
switch (gestureRecognizer.state) {
case UIGestureRecognizerStateEnded:{ // UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded
NSLog(@"======UIGestureRecognizerStateEnded || UIGestureRecognizerStateRecognized");
break;
}
case UIGestureRecognizerStateBegan:{ //
NSLog(@"======UIGestureRecognizerStateBegan");
break;
}
case UIGestureRecognizerStateChanged:{ //
NSLog(@"======UIGestureRecognizerStateChanged");
break;
}
case UIGestureRecognizerStateCancelled:{ //
NSLog(@"======UIGestureRecognizerStateCancelled");
break;
}
case UIGestureRecognizerStateFailed:{ //
NSLog(@"======UIGestureRecognizerStateFailed");
break;
}
case UIGestureRecognizerStatePossible:{ //
NSLog(@"======UIGestureRecognizerStatePossible");
break;
}
default:{
NSLog(@"======Unknow gestureRecognizer");
break;
}
}
}
// 詢問一個(gè)手勢(shì)接收者是否應(yīng)該開始解釋執(zhí)行一個(gè)觸摸接收事件
-
(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
CGPoint currentPoint = [gestureRecognizer locationInView:self.view];
if (CGRectContainsPoint(CGRectMake(0, 0, 100, 100), currentPoint) ) {
return YES;
}
return NO;
}
// 詢問delegate献丑,兩個(gè)手勢(shì)是否同時(shí)接收消息末捣,返回YES同事接收侠姑。返回NO,不同是接收(如果另外一個(gè)手勢(shì)返回YES箩做,則并不能保證不同時(shí)接收消息)the default implementation returns NO莽红。
// 這個(gè)函數(shù)一般在一個(gè)手勢(shì)接收者要阻止另外一個(gè)手勢(shì)接收自己的消息的時(shí)候調(diào)用
-
(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return NO;
}
// 詢問delegate是否允許手勢(shì)接收者接收一個(gè)touch對(duì)象
// 返回YES,則允許對(duì)這個(gè)touch對(duì)象審核,NO安吁,則不允許醉蚁。
// 這個(gè)方法在touchesBegan:withEvent:之前調(diào)用,為一個(gè)新的touch對(duì)象進(jìn)行調(diào)用
-
(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
return YES;
}