iOS手势处理

iOS手势处理

iOS手势有着如下几种:

上面的手势对应的操作是:

  • Tap         
    (点一下)

  • Pinch       
    (二指往內或往外拨动,平时经常用到的缩放)  矩阵变换

  • Rotation   
    (旋转)                                                 
    矩阵变换

  • Swipe      
    (滑动,快速移动)

  • Pan         
    (拖移,慢速移动)                                    
    矩阵变换

  • LongPress
    (长按)

注意:以下示例均把手势封装进一个View当中

UITapGestureRecognizer -
点击手势

GestureView.h + GestureView.m

#import <UIKit/UIKit.h>

@interface GestureView : UIView

@end

GestureView.h

#import "GestureView.h"

@interface GestureView ()
@property (nonatomic, strong) UITapGestureRecognizer *tapGesture;
@property (nonatomic, strong) CALayer *colorLayer;
@end

@implementation GestureView

- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// 初始化手势,给手势指定响应事件的对象
_tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(gestureEvent:)];
_colorLayer = [CALayer layer];
_colorLayer.frame = self.bounds;

[self.layer addSublayer:_colorLayer];

// 将手势与区域绑定
[self addGestureRecognizer:_tapGesture];
}
return self;
}

- (void)gestureEvent:(UIGestureRecognizer *)sender {
_colorLayer.backgroundColor = [UIColor colorWithRed:arc4random() % 255 / 255.f
green:arc4random() % 255 / 255.f
blue:arc4random() % 255 / 255.f
alpha:1.0f].CGColor;
}

@end

GestureView.m

- (void)addGestureRecognizer:(UIGestureRecognizer
*)gestureRecognizer

Attaching a gesture recognizer to a view defines the scope of the
represented gesture, causing it to receive touches hit-tested to that view
and all of its subviews. The view establishes a strong reference to the
gesture recognizer.

将手势识别器附着在一个view上,实际上定义了一个手势接收的区域,会将接收到的触摸事件传递给这个view以及这个view的说有的subviews.这个view会对这个手势识别器强引用.

可以总结两点:

1.
手势会传递给这个view中所有的subviews

2. view会强引用手势识别器

使用如下:

点击手势有两个参数可以设置:

numberOfTapsRequired        
点击几次触发事件(默认是1)

numberOfTouchesRequired    需要几个手指点击(默认是1)

UIPinchGestureRecognizer
-
缩放

GestureView.h + GestureView.m

#import <UIKit/UIKit.h>

@interface GestureView : UIView

@end

GestureView.h

#import "GestureView.h"

@interface GestureView ()
@property (nonatomic, strong) UIPinchGestureRecognizer *pinchGesture;
@end

@implementation GestureView

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// 初始化手势,给手势指定响应事件的对象
_pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self
action:@selector(gestureEvent:)];

// 将手势与区域绑定
[self addGestureRecognizer:_pinchGesture];
}
return self;
}

- (void)gestureEvent:(UIPinchGestureRecognizer *)sender
{
//
self.transform = CGAffineTransformScale(self.transform, sender.scale, sender.scale);
sender.scale = 1;
}

@end


GestureView.m

缩放手势会用到矩阵变换.

UIRotationGestureRecognizer
- 旋转

GestureView.h + GestureView.m

#import <UIKit/UIKit.h>

@interface GestureView : UIView

@end

GestureView.h

#import "GestureView.h"

@interface GestureView ()
@property (nonatomic, strong) UIRotationGestureRecognizer *rotationGesture;
@end

@implementation GestureView

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// 初始化手势,给手势指定响应事件的对象
_rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self
action:@selector(gestureEvent:)];

// 将手势与区域绑定
[self addGestureRecognizer:_rotationGesture];
}
return self;
}

- (void)gestureEvent:(UIRotationGestureRecognizer *)sender
{
// 此处用到了矩阵变换
self.transform = CGAffineTransformRotate(self.transform, sender.rotation);
sender.rotation = 0;
}


GestureView.m

UISwipeGestureRecognizer
- 滑动

GestureView.h + GestureView.m

#import <UIKit/UIKit.h>

@interface GestureView : UIView

@end

GestureView.h

#import "GestureView.h"

@interface GestureView ()
@property (nonatomic, strong) UISwipeGestureRecognizer *swipeGesture;
@end

@implementation GestureView

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// 初始化手势,给手势指定响应事件的对象
_swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self
action:@selector(gestureEvent:)];
_swipeGesture.direction = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight;

// 将手势与区域绑定
[self addGestureRecognizer:_swipeGesture];
}
return self;
}

- (void)gestureEvent:(UISwipeGestureRecognizer *)sender
{
NSLog(@"left or right");
}

@end

GestureView.m

UIPanGestureRecognizer -
平移

GestureView.h + GestureView.m

#import <UIKit/UIKit.h>

@interface GestureView : UIView

@end

GestureView.h

#import "GestureView.h"

@interface GestureView ()
@property (nonatomic, strong) UIPanGestureRecognizer *panGesture;
@end

@implementation GestureView

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// 初始化手势,给手势指定响应事件的对象
_panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self
action:@selector(gestureEvent:)];

// 将手势与区域绑定
[self addGestureRecognizer:_panGesture];
}
return self;
}

- (void)gestureEvent:(UIPanGestureRecognizer *)sender
{
// 此处用到了矩阵变换
CGPoint translation = [sender translationInView:self];

self.center = CGPointMake(self.center.x + translation.x,
self.center.y + translation.y);

[sender setTranslation:CGPointZero
inView:self];
}

@end

GestureView.m

UILongPressGestureRecognizer
- 长按手势

GestureView.h + GestureView.m

#import <UIKit/UIKit.h>

@interface GestureView : UIView

@end

GestureView.h

#import "GestureView.h"

@interface GestureView ()
@property (nonatomic, strong) UILongPressGestureRecognizer *longPressGesture;
@end

@implementation GestureView

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
// 初始化手势,给手势指定响应事件的对象
_longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self
action:@selector(gestureEvent:)];
_longPressGesture.minimumPressDuration = 2.0f;

// 将手势与区域绑定
[self addGestureRecognizer:_longPressGesture];
}
return self;
}

- (void)gestureEvent:(UILongPressGestureRecognizer *)sender
{
NSLog(@"触发事件");
}

@end

GestureView.m

问题:如何处理一个view中添加了两个手势,1个是单击的手势,一个是双击的手势呢?

可以使用这个方法requireGestureRecognizerToFail:

#import "GestureView.h"

@interface GestureView ()
@property (nonatomic, strong) UITapGestureRecognizer *tapGesture1;
@property (nonatomic, strong) UITapGestureRecognizer *tapGesture2;
@end

@implementation GestureView

- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// 单击手势
_tapGesture1 = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(gesture1Event:)];
_tapGesture1.numberOfTapsRequired = 1;

// 双击手势
_tapGesture2 = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(gesture2Event:)];
_tapGesture2.numberOfTapsRequired = 2;

// 注意: 判断双击手势需要时间,也就是说会有延时

// 有事件触发时,先判断是不是 双击手势,如果不是就执行 单击手势
[_tapGesture1 requireGestureRecognizerToFail:_tapGesture2];

// 将手势与区域绑定
[self addGestureRecognizer:_tapGesture1];
[self addGestureRecognizer:_tapGesture2];
}
return self;
}

- (void)gesture1Event:(UIGestureRecognizer *)sender {
NSLog(@"1");
}

- (void)gesture2Event:(UIGestureRecognizer *)sender {
NSLog(@"2");
}

@end

GestureView.m

实际上,这种方式会有延时感-_-!!!!

问题:如何将长按手势和拖拽手势合并在一起呢?

我们需要用代理实现,实现以下的方法:

-
(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer
*)otherGestureRecognizer

Asks the delegate if two gesture
recognizers should be allowed to recognize gestures
simultaneously.

询问这个代理,是否允许两个手势同时触发.

#import "GestureView.h"

@interface GestureView ()<UIGestureRecognizerDelegate>

{
BOOL shouldAllowPan;
}

@property (nonatomic, strong) UIPanGestureRecognizer *panGesture;
@property (nonatomic, strong) UILongPressGestureRecognizer *longPressGesture;
@end

@implementation GestureView

- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// 初始化时不允许拖拽
shouldAllowPan = NO;

_panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self
action:@selector(panEvent:)];
[self addGestureRecognizer:_panGesture];
_panGesture.delegate = self;

_longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self
action:@selector(longPressEvent:)];
_longPressGesture.minimumPressDuration = 1.0f;
[self addGestureRecognizer:_longPressGesture];
_longPressGesture.delegate = self;
}
return self;
}

- (void)panEvent:(UIPanGestureRecognizer *)sender {

if(shouldAllowPan == YES)
{
// 移动的操作
CGPoint translation = [sender translationInView:self];
self.center = CGPointMake(self.center.x + translation.x,
self.center.y + translation.y);

[sender setTranslation:CGPointZero
inView:self];
}
else if(sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateFailed || sender.state == UIGestureRecognizerStateCancelled)
{
shouldAllowPan = NO;
}
}

- (void)longPressEvent:(UIGestureRecognizer *)sender
{
// 长按开始
if(UIGestureRecognizerStateBegan == sender.state)
{
NSLog(@"长按开始");
self.backgroundColor = [UIColor redColor];
shouldAllowPan = NO;
}

// 长按进行中
if(UIGestureRecognizerStateChanged == sender.state)
{
NSLog(@"长按进行中");
shouldAllowPan = YES;
}

// 长按结束
if(UIGestureRecognizerStateEnded == sender.state)
{
NSLog(@"长按结束");
self.backgroundColor = [UIColor blackColor];
shouldAllowPan = NO;
}
}

// 是否允许多个手势同时触发
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
// 允许
return YES;
}

// 是否允许继续跟踪触摸事件
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
// 条件满足的手势会被传递进来(如果是移动手势,)
if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && shouldAllowPan == NO)
{
return NO;
}

return YES;
}

@end

GestureView.m

根据手势状态来识别手势触发事件的全称细节是十分重要的.

iOS手势处理

时间: 2024-10-10 09:18:40

iOS手势处理的相关文章

iOS手势学习UIGestureRecognizer &amp; cocos2d 手势推荐

iOS手势学习UIGestureRecognizer & cocos2d 手势推荐 手势识别类型: UILongPressGestureRecognizer  // 长按UIPanGestureRecognizer  // 慢速拖动UIPinchGestureRecognizer  // 两指向內或向外拨动UIRotationGestureRecognizer   // 旋转UISwipeGestureRecognizer   // 快速滑动UITapGestureRecognizer   //

iOS手势 规避同一界面上不同子界面同时响应多个手势

最近在项目中遇到这样一个有关iOS手势的问题,首先需求描述如下:“在一个CollectionView中,要求长按不同的cell,产生一个cell的snapshot,此时可拖拽这个snapshot再进行后续的操作(如拖到view的某个位置出发一个事件)”.需求本身并不复杂,但要求每次只能有一个cell响应长按手势,不允许同时有两个或以上的cell响应长按手势. 我们知道UIGestureRecognizer有很多回调和方法可以兼容同一个View上的多种手势,网上相关的教程也很多,比如: http:

iOS手势UIGestureRecognizer

UIGestureRecognizer是一个抽象类,定义了所有手势的基本行为,它有6个子类处理具体的手势: 1.UITapGestureRecognizer (任意手指任意次数的点击) // 点击次数 numberOfTapsRequired // 手指个数 numberOfTouchesRequired [plain] view plaincopy UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer a

iOS手势UIGestureRecognizer识别的详细使用(拖动,缩放,旋转,点击,手势依赖,自定义手势) (转)

1.UIGestureRecognizer介绍 手势识别在iOS上非常重要,手势操作移动设备的重要特征,极大的增加了移动设备使用便捷性. iOS系统在3.2以后,为方便开发这使用一些常用的手势,提供了UIGestureRecognizer类.手势识别UIGestureRecognizer类是个抽象类,下面的子类是具体的手势,开发这可以直接使用这些手势识别. UITapGestureRecognizer UIPinchGestureRecognizer UIRotationGestureRecog

iOS 手势识别器概述

手势识别器 iOS 手势识别器(UIGestureRecognizer) 点击手势(UITapGestureRecognizer) 滑动手势(UISwipeGestureRecognizer) 旋转手势(UIRotationGestureRecognizer) 捏合手势( UIPinchGestureRecognizer) 长按手势( UILongPressGestureRecognizer) 平移手势( UIPanGestureRecognizer) 屏幕边缘平移手势(UIScreenEdge

iOS手势识别器

UIGestureRecognizer UIGestureRecognizer类,用于检测.识别用户使用设备时所用的手势.它是一个抽象类,定义了所有手势的基本行为.以下是UIGestureRecognizer子类,用于处理具体的用户手势行为: UITapGestureRecognizer // 1.单击 UILongPressGestureRecognizer // 3.长按 UISwipeGestureRecognizer // 4.轻扫 UIPanGestureRecognizer // 5

iOS 手势及触摸

转自:http://justsee.iteye.com/blog/1885538 一.响应链 在IOS开发中会遇到各种操作事件,通过程序可以对这些事件做出响应. 首先,当发生事件响应时,必须知道由谁来响应事件.在IOS中,由响应者链来对事件进行响应,所有事件响应的类都是UIResponder的子类, 响应者链是一个由不同对象组成的层次结构,其中的每个对象将依次获得响应事件消息的机会.当发生事件时,事件首先被发送给第一响应者,第一响应者往往是事 件发生的视图,也就是用户触摸屏幕的地方.事件将沿着响

iOS手势操作,拖动,轻击,捏合,旋转,长按,自定义(http://www.cnblogs.com/huangjianwu/p/4675648.html)

1.UIGestureRecognizer 介绍 手势识别在 iOS 中非常重要,他极大地提高了移动设备的使用便捷性. iOS 系统在 3.2 以后,他提供了一些常用的手势(UIGestureRecognizer 的子类),开发者可以直接使用他们进行手势操作. UIPanGestureRecognizer(拖动) UIPinchGestureRecognizer(捏合) UIRotationGestureRecognizer(旋转) UITapGestureRecognizer(点按) UILo

IOS 手势事件的冲突

关于手操作需要强调几点: UIImageView默认是不支持交互的,也就是userInteractionEnabled=NO ,因此要接收触摸事件(手势识别),必须设置userInteractionEnabled=YES(在iOS中UILabel.UIImageView的userInteractionEnabled默认都是NO,UIButton.UITextField.UIScrollView.UITableView等默认都是YES). 轻扫手势虽然是连续手势但是它的操作事件只会在识别结束时调用