手势UIGestureRecognizer
来源:互联网 发布:linux查看网口状态 编辑:程序博客网 时间:2024/05/03 18:25
UIGestureRecognizer 是识别手势类的抽象基类。
UIGestureRecognizer 有以下子类:
UITapGestureRecognizer
UIPinchGestureRecognizer
UIRotationGestureRecognizer
UISwipeGestureRecognizer
UIPanGestureRecognizer
UIScreenEdgePanGestureRecognizer
UILongPressGestureRecognizer
- 上面的手势对应的操作是:
- Tap(点一下)
- Pinch(二指往內或往外拨动,平时经常用到的缩放)
- Rotation(旋转)
- Swipe(滑动,快速移动)
- Pan (拖移,慢速移动)
- ScreenEdgePan(屏蔽边缘)
- LongPress(长按)
通过内置的手势识别器来处理一个手势的基本流程如下所示:
1.创建一个具有正确类型的对象,作为想要实现的手势识别器;
2.把该对象作为手势识别器添加到需要接收手势的视图中;
3.书写一个方法,该方法当手势事件发生时被调用,由其来执行应用所需的动作。
一般,Tap、pinch,pan、swipe只是一个简单的单个触摸,它有一定的局限性,所以多点触摸诞生了~为实现多点触摸,首先得做下列事情:
1.设置view的属性multipleTouchEnabled = YES(注意了。。。默认值是NO);
2.使用CFDictionaryRef来保存触摸过程的参数 。UIControl子类会覆盖parentView的gesture。例如当用户点击UIButton时,UIButton会接受触摸事件,它的parentView不会接收到。
UIGestureRecognizer 类定义了一组常用的方法,可用于所有具体的手势识别。也可以和代理(UIGestureRecognizerDelegate协议)实现一些行为。每一个特定的手势必须关联到view对象中才会有作用,一个view对象可以关联多个不同的特定手势,但是每一个特定的手势只能与一个view相关联。当用户触摸了view,这个GestureRecognizer就会接受到消息,它可以响应特定的触摸事件。使用addGestureRecognizer函数来将手势和view对象关联起来,例如:
[snakeImageView addGestureRecognizer:panGestureRecognizer];
初始化一个手势类别:
1.初始化:
- (instancetype)initWithTarget:(id)target action:(SEL)action例如:
UIImageView *snakeImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"snake.png"]]; snakeImageView.frame = CGRectMake(50, 50, 100, 160); UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)]; [snakeImageView addGestureRecognizer:panGestureRecognizer]; [self.view setBackgroundColor:[UIColor whiteColor]]; [self.view addSubview:snakeImageView];初始化一个Pan拖动手势手势,并添加到UIImageView视图上,并创建回调方法:
- (void) handlePan:(UIPanGestureRecognizer*) recognizer{ //......}一个方法,若其作为目标方法被绑定到手势识别器中,,它需要遵循下面的规则:
(1).必须返回void
(2).要么不接收任何参数,要么接收一个类型为UIGestureRecogonizer的参数,系统使用这个参数向该方法传递调用该方法的手势识别器
如下:
- (void)handleGesture;- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer;
添加、移除手势的目标和行为方法:
2.添加方法:
- (void)addTarget:(id)target action:(SEL)action你可以多次调用这个方法为目标手势添加方法。如果目标重复添加,请求消息被忽略。
3.移除手势识别器的指定方法:
- (void)removeTarget:(id)target action:(SEL)action
获取触摸发生手势的位置:
4.返回一个给定视图发生手势的点:
- (CGPoint)locationInView:(UIView *)view返回在视图识别手势的位置的局部坐标系统(响应者坐标系统)的一个点(CGPoint)。如果没有指定视图(nil),该方法返回基于窗口坐标系统的发生手势的点(CGPoint)。
返回的点通常是手势的触摸中心。
5.返回一个给定视图发生手势的点(为了在多个手势中捕获位置):
- (CGPoint)locationOfTouch:(NSUInteger)touchIndex inView:(UIView *)viewtouchIndex是UITouch对象的私有数组索引。
6.触摸点的个数:
- (NSUInteger)numberOfTouches
7.手势状态:
@property(nonatomic, readonly) UIGestureRecognizerState state
8.触发手势的视图(一般在触摸执行操作中我们可以通过此属性获得触摸视图进行操作):
@property(nonatomic, readonly) UIView *view
9.手势是否可用:
@property(nonatomic, getter=isEnabled) BOOL enabled
取消和延迟触动:
10.解除View上的绑定的剩余手势事件:
@property(nonatomic) BOOL cancelsTouchesInView
如果Recognizer分析成功,就会解除View上的绑定的剩余手势事件,那么windows也不会给发送这写手势事件。windows通过给view发送touchesCancelled:withEvent:消息来退出旧事件处理。
cancelsTouchesInView默认为YES,表示当Gesture Recognizers识别到手势后,会向hit-test view发送 touchesCancelled:withEvent:消息来取消hit-test view对此触摸序列的处理,这样只有Gesture Recognizers能响应此触摸序列,hit-test view不再响应。如果为NO,则不发送touchesCancelled:withEvent:消息给hit-test view,这样会使Gesture Recognizers和hit-test view同时响应触摸序列。
@property(nonatomic) BOOL delaysTouchesBegan
delaysTouchesBegan默认为NO,表示触摸序列开始时,而手势识别器还未识别出此手势时,touch事件会同时发向hit-test view,这样在手势识别器还未识别出此手势,hit-test view同时也可以收到同样的触摸事件。如果为YES,则在手势识别器在识别手势的过程中,不会有任何触摸事件发送给hit-test view,如果手势识别器最终识别到了手势,则也不会发送任何消息(包括touchesCancelled:withEvent:)给hit-test view;若干手势识别最终没有识别到手势,则所有的触摸事件在发给hit-test view处理。关于这个特性,可参考UIScrollView的delaysContentTouches属性。这样属性也谨慎使用,使用不当会导致UI无响应。
@property(nonatomic) BOOL delaysTouchesEnded如果分析成功,就不会给View发送手势事件对象( UITouchPhaseEnded),但是会发送touchesCancelled:withEvent消息,如果失败才发送 touchesEnded:withEvent:。默认是YES。
delaysTouchesEnded,在文档上的解释是,当手势识别器在识别手势时,对于UITouchPhaseEnded阶段的touch会延迟发送给hit-test view,在手势识别成功后,发送给hit-test view cancel消息,手势识别失败时,发送原来的end消息。其给出了了这样的例子识别双击操作的UITapGestureRecognizer对象,其numberOfTapsRequired设为2,在用户进行双击操作时,如果delaysTouchesEnded为NO,则hit-test view中的调用序列为
touchesBegan:withEvent:,
touchesEnded:withEvent:,
touchesBegan:withEvent:,
and touchesCancelled:withEvent:
如果delaysTouchesEnded为YES,则调用序列为:
touchesBegan:withEvent:,
touchesBegan:withEvent:,
touchesCancelled:withEvent:,
touchesCancelled:withEvent:
但我在实际测试时,并非如此,实际测试的结果是,如果delaysTouchesEnded为NO,则调用序列为:
touchesBegan:withEvent:,
touchesEnded:withEvent:,
TapGestureRecognizer 检测到双击
如果delaysTouchesEnded为YES,则调用序列为:
touchesBegan:withEvent:,
touchesEnded:withEvent:,
TapGestureRecognizer 检测到双击
touchesCancelled:withEvent:
13.指定一个手势需要另一个手势失败才能执行:
- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer例如:
// 如果双击确定偵測失败才會触发单击 [singleRecognizer requireGestureRecognizerToFail:doubleRecognizer];
设置和获取代理:
14.手势代理:
@property(nonatomic, assign) id< UIGestureRecognizerDelegate > delegate
子类方法:
15.一根或多根手指开始触摸屏幕时执行:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
16.一根或多根手指在屏幕上移动时执行,注意此方法在移动过程中会重复调用:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
17.一根或多根手指触摸结束离开屏幕时执行:
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
18.触摸意外取消时执行(例如正在触摸时打入电话):
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
19.手势结束时重写此方法重置内部状态:
- (void)reset
20.忽略一个特定的事件:
- (void)ignoreTouch:(UITouch *)touch forEvent:(UIEvent *)event
21.重写显示指定的手势识别器可以防止接收从识别手势:
- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer
22.防止从指定手势接收器接收别的手势:
- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer
想控制两个识别器相互作用,但你需要指定一个单向关系,您可以重写或canPreventGestureRecognizer:或canBePreventedByGestureRecognizer:子类方法。return yes。例如,如果你想要一个旋转的姿态来防止捏动作,但你不想夹手势防止旋转的姿态。例如,你想一个旋转手势阻止一个缩放手势,但你不想一个缩放手势阻止旋转手势,就加入下面代码:
[rotationGestureRecognizer canPreventGestureRecognizer:pinchGestureRecognizer];
23.
- (BOOL)shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
24.
- (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
数据类型:
25.手势识别状态:
typedef NS_ENUM(NSInteger, UIGestureRecognizerState) { UIGestureRecognizerStatePossible, // 尚未识别是何种手势操作(但可能已经触发了触摸事件),默认状态 UIGestureRecognizerStateBegan, // 手势已经开始,此时已经被识别,但是这个过程中可能发生变化,手势操作尚未完成 UIGestureRecognizerStateChanged, // 手势状态发生转变 UIGestureRecognizerStateEnded, // 手势识别操作完成(此时已经松开手指) UIGestureRecognizerStateCancelled, // 手势被取消,恢复到默认状态 UIGestureRecognizerStateFailed, // 手势识别失败,恢复到默认状态 UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded // 手势识别完成,同UIGestureRecognizerStateEnded};
状态转换离散/连续的手势:
iOS的手势识别模型其实是一个状态机
所有手势识别从一个可能状态(UIGestureRecognizerStatePossible)开始,然后开始分析、识别手势,如果识别失败将会进入失败状态 (UIGestureRecognizerStateFailed)。
如果识别成功,进入成功状态(UIGestureRecognizerStateRecognized)
对于连续性的手势,手势识别从Possible进入Began(UIGestureRecognizerStateBegan) ,然后会进入Change (UIGestureRecognizerStateChanged)状态,并在Change状态循环,在最后用户手指离开屏幕的时候会进入End(UIGestureRecognizerStateEnded)状态
连续手势也会从Change进入cancel (UIGestureRecognizerStateCancelled),如果判断手势已经不符合该要求了。
每次Gesture recognizer改变状态的时候都会发送一个action message到target,知道Failed或者Cancel。
有时候会出现iOS判断该手势符合多个条件,而用户此时只想要其中一种,这个情况下可以调用 requireGestureRecognizerToFail: ,该方法会让当前手势对象根据指定对象状态来进行下一步操作。如果指定对象进入Begin状态,当前对象直接进入Failed;如果指定对象进入Failed或Cancel状态,当前对象会进入Begin状态。这里就涉及到了不同手势之间执行的问题。(如果想要单击和双击都要执行,并分别执行不同的逻辑,这里可以先让单机等待双击失败在执行,但这样会导致单击事件稍微延迟执行,因为单击事件需要等待双击事件失败)。
可以选择不让接收、分析手势事件,通过 gestureRecognizer:shouldReceiveTouch: 在最开始的时候允许、拒绝接收手势时间;如果想延后判断则可以通过 gestureRecognizerShouldBegin:,如果返回No则会导致Failed时间
如果想要同时接收两个事件,就调用gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: 默认这个方法返回No,返回Yes则运行同时运行
单向影响,事件A和B, 如果想要让A影响B,但不想让B影响A,则可以通过重载方法 canPreventGestureRecognizer: 或者canBePreventedByGestureRecognizer:实现,比如
[rotationGestureRecognizer canPreventGestureRecognizer:pinchGestureRecognizer];
Touch事件传递过程是上到下,也就是从App->Window->View的过程
Touch事件,window会让Gesture recognizer优先分析touch对象,如果Gesture recognizer成功识别这些对象,touch事件就不会执行。总结就是Gesture recognizer的优先级会低于touch事件
影响touch传递给views
delaysTouchesBegan 阻止在Begin阶段Windows交付touch事件
delaysTouchesEnded Window不会在Enable阶段交付Touch事件
Gesture Recognizer是iOS定制的一些Touch事件类型,Dev可以订制自己的Gesture Recognizer,这里要继承UIGestureRecognizer并覆盖主要的四个类。
子类:
UILongPressGestureRecognizer(长按)
配置手势:
1.最少持续多少秒手势才回被识别:
@property(nonatomic) CFTimeInterval minimumPressDuration该属性表明用户需要在屏幕上按多长时间才可以触发手势识别事件,以秒为单位。
2.屏幕上必须出现的手指数量:
@property(nonatomic) NSUInteger numberOfTouchesRequired
该属性是指需要多少根手指触碰屏幕才可以触发手势识别。如果numberOfTapsRequired属性设置的值大于0,则你的必须要指定相同数目的手指来检测点击。
3.点击多少次才可以触发手势识别:
@property(nonatomic) NSUInteger numberOfTapsRequired该属性用以确定用户需要在目标视图上点击的次数,才可以触发手势识别。请记住,点击不仅仅是手指放在屏幕上。一次点击是指将手指放到屏幕上,然后再抬起手指的整个运动过程。该属性的默认值为0。
4.在手势识别取消之前,手指可以在屏幕上移过的最大像素数:
@property(nonatomic) CGFloat allowableMovement手指按下后事件响应前允许手指移动的偏移量。
UIPanGestureRecognizer(拖移,慢速移动)
配置手势:
1.最大/小几根手指可激活拖动手势识别器:
@property(nonatomic) NSUInteger maximumNumberOfTouches
@property(nonatomic) NSUInteger minimumNumberOfTouches
跟踪手势的位置和速度:
1.拖移手势在指定视图中的坐标系统的转换:
- (CGPoint)translationInView:(UIView *)view
2.在指定的视图中的坐标系统中设定转换值:
- (void)setTranslation:(CGPoint)translation inView:(UIView *)view
3.获得手势速度:
- (CGPoint)velocityInView:(UIView *)view
@property(nonatomic) CGFloat scale
2.挤捏的速度,以多少像素每秒为单位:
@property(nonatomic, readonly) CGFloat velocity当出点彼此接近时,该速度为负值,而当触点彼此远离时,该速度为正值。
UIRotationGestureRecognizer(旋转)
理解手势:
1.使用弧度单位来定义用户手势的旋转总量以及方向:
@property(nonatomic) CGFloat rotation旋转有手指的初始位置(UIRotationGestureRecognizerStateBegan)以及最终位置(UIRotationGestureRecognizerStateEnded)来决定。
2.旋转的速度:
@property(nonatomic, readonly) CGFloat velocity
配置手势:
1.方向控制:
@property(nonatomic) UISwipeGestureRecognizerDirection direction默认的方向是uiswipegesturerecognizerdirectionright。更多信息见uiswipegesturerecognizerdirection类型常数的描述。
2.屏幕上必须出现的手指数量:
@property(nonatomic) NSUInteger numberOfTouchesRequired
该属性是指需要多少根手指触碰屏幕才可以触发手势识别。如果numberOfTapsRequired属性设置的值大于0,则你的必须要指定相同数目的手指来检测点击。
数据类型:3.方向:
typedef enum { UISwipeGestureRecognizerDirectionRight = 1 << 0, UISwipeGestureRecognizerDirectionLeft = 1 << 1, UISwipeGestureRecognizerDirectionUp = 1 << 2, UISwipeGestureRecognizerDirectionDown = 1 << 3} UISwipeGestureRecognizerDirection;
UITapGestureRecognizer(点一下)
配置手势:
1.
点击多少次才可以触发手势识别:
@property(nonatomic) NSUInteger numberOfTapsRequired该属性用以确定用户需要在目标视图上点击的次数,才可以触发手势识别。请记住,点击不仅仅是手指放在屏幕上。一次点击是指将手指放到屏幕上,然后再抬起手指的整个运动过程。该属性的默认值为0。
- 手势UIGestureRecognizer
- 手势UIGestureRecognizer
- UIGestureRecognizer手势
- UIGestureRecognizer 手势
- 手势UIGestureRecognizer
- 手势UIGestureRecognizer
- UIGestureRecognizer手势
- UIGestureRecognizer手势
- UIGestureRecognizer手势
- UIGestureRecognizer手势
- UIGestureRecognizer手势
- 使用iOS手势UIGestureRecognizer
- 使用iOS手势UIGestureRecognizer
- 使用iOS手势UIGestureRecognizer
- 使用iOS手势UIGestureRecognizer
- iOS手势UIGestureRecognizer
- 使用iOS手势UIGestureRecognizer
- 使用iOS手势UIGestureRecognizer
- 软件
- pad键盘挡住EditText与输入的时候空白的现象
- 金现代实习,jQuery学习
- linux mtd层ecc详解
- hdu 4939 Stupid Tower Defense 2014 Multi-University Training Contest 7
- 手势UIGestureRecognizer
- Android学习之AutoCompleteTextView
- Hash Sum mismatch
- 最小生成树---Kruskal算法
- Hibernate 所有缓存机制详解
- NSArray NSMutableArray
- Apache Spark学习:利用Scala语言开发Spark应用程序
- 利用SQL Server发送邮件
- POJ 3090 Visible Lattice Points