iOS事件机制,以及不同手势使用touchesBegan等表现形式

iOS事件机制,以及不同手势使用touchesBegan等表现形式事件处理方法UIResponder中定义了一系列对事件的处理方法,他们分别是:–(void)touchesBegan:(NSSet )toucheswithEvent:(UIEvent

大家好,又见面了,我是你们的朋友全栈君。

事件处理方法

UIResponder中定义了一系列对事件的处理方法,他们分别是:

  • –(void)touchesBegan:(NSSet )touches withEvent:(UIEvent )event
  • –(void)touchesMoved:(NSSet )touches withEvent:(UIEvent )event
  • –(void)touchesEnded:(NSSet )touches withEvent:(UIEvent )event
  • –(void)touchesCancelled:(NSSet )touches withEvent:(UIEvent )event

从方法名字可以知道,他们分别对应了屏幕事件的开始、移动、结束和取消几个阶段,前三个阶段理解都没问题,最后一个取消事件的触发时机是在诸如突然来电话或是系统杀进程时调用。这些方法的第一个参数定义了UITouch对象的一个集合(NSSet),它的数量表示了这次事件是几个手指的操作,目前iOS设备支持的多点操作手指数最多是5。第二个参数是当前的UIEvent对象。下图展示了一个UIEvent对象与多个UITouch对象之间的关系。

<span role="heading" aria-level="2">iOS事件机制,以及不同手势使用touchesBegan等表现形式

一、点击事件

首先,新建一个自定义的View继承于UIView,并实现上述提到的事件处理方法,我们可以通过判断UITouch的tapCount属性来决定响应单击、双击或是多次点击事件。

MyView.m

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 
#import "MyView.h" @implementation MyView -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { } -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {  for (UITouch *aTouch in touches) {  if (aTouch.tapCount == 2) {  // 处理双击事件  [self respondToDoubleTapGesture];  }  } } -(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { } -(void)respondToDoubleTapGesture {  NSLog(@"respondToDoubleTapGesture"); } @end 

二、滑动事件

滑动事件一般包括上下滑动和左右滑动,判断是否是一次成功的滑动事件需要考虑一些问题,比如大部分情况下,用户进行一次滑动操作,这次滑动是否是在一条直线上?或者是否是基本能保持一条直线的滑动轨迹。或者判断是上下滑动还是左右滑动等。另外,滑动手势一般有一个起点和一个终点,期间是在屏幕上画出的一个轨迹,所以需要对这两个点进行判断。我们修改上述的MyView.m的代码来实现一次左右滑动的事件响应操作。

MyView.m

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 
#import "MyView.h" #define HORIZ_SWIPE_DRAG_MIN 12 //水平滑动最小间距 #define VERT_SWIPE_DRAG_MAX 4 //垂直方向最大偏移量 @implementation MyView -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {  UITouch *aTouch = [touches anyObject];  // startTouchPosition是一个CGPoint类型的属性,用来存储当前touch事件的位置  self.startTouchPosition = [aTouch locationInView:self]; } -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {  UITouch *aTouch = [touches anyObject];  CGPoint currentTouchPosition = [aTouch locationInView:self];  // 判断水平滑动的距离是否达到了设置的最小距离,并且是否是在接近直线的路线上滑动(y轴偏移量)  if (fabsf(self.startTouchPosition.x - currentTouchPosition.x) >= HORIZ_SWIPE_DRAG_MIN &&  fabsf(self.startTouchPosition.y - currentTouchPosition.y) <= VERT_SWIPE_DRAG_MAX)  {  // 满足if条件则认为是一次成功的滑动事件,根据x坐标变化判断是左滑还是右滑  if (self.startTouchPosition.x < currentTouchPosition.x) {  [self rightSwipe];//右滑响应方法  } else {  [self leftSwipe];//左滑响应方法  }  //重置开始点坐标值  self.startTouchPosition = CGPointZero;  } } -(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {  //当事件因某些原因取消时,重置开始点坐标值  self.startTouchPosition = CGPointZero; } -(void)rightSwipe {  NSLog(@"rightSwipe"); } -(void)leftSwipe {  NSLog(@"leftSwipe"); } @end 

三、拖拽事件

在屏幕上我们可以拖动某一个控件(View)进行移动,这种事件成为拖拽事件,其实现原理就是在不改变View的大小尺寸的前提下改变View的显示坐标值,为了达到动态移动的效果,我们可以在move阶段的方法中进行坐标值的动态更改,还是重写MyView.m的事件处理方法,这次在touchesMove方法中进行处理。

MyView.m

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 
#import "MyView.h" @implementation MyView -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { } -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {  UITouch *aTouch = [touches anyObject];  //获取当前触摸操作的位置坐标  CGPoint loc = [aTouch locationInView:self];  //获取上一个触摸点的位置坐标  CGPoint prevloc = [aTouch previousLocationInView:self];  CGRect myFrame = self.frame;  //改变View的x、y坐标值  float deltaX = loc.x - prevloc.x;  float deltaY = loc.y - prevloc.y;  myFrame.origin.x += deltaX;  myFrame.origin.y += deltaY;  //重新设置View的显示位置  [self setFrame:myFrame]; } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { } -(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { } @end 

四、双指缩放

之前提到过UIEvent包含了一系列的UITouch对象构成一次事件,当设计多点触控操作时,可与对UIEvent对象内的UITouch对象进行处理,比如实现一个双指缩放的功能。

MyView.m

1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 
#import "MyView.h" @implementation MyView {  BOOL pinchZoom;  CGFloat previousDistance;  CGFloat zoomFactor; } -(id)init {  self = [super init];  if (self) {  pinchZoom = NO;  //缩放前两个触摸点间的距离  previousDistance = 0.0f;  zoomFactor = 1.0f;  }  return self; } -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {  if(event.allTouches.count == 2) {  pinchZoom = YES;  NSArray *touches = [event.allTouches allObjects];  //接收两个手指的触摸操作  CGPoint pointOne = [[touches objectAtIndex:0] locationInView:self];  CGPoint pointTwo = [[touches objectAtIndex:1] locationInView:self];  //计算出缩放前后两个手指间的距离绝对值(勾股定理)  previousDistance = sqrt(pow(pointOne.x - pointTwo.x, 2.0f) +  pow(pointOne.y - pointTwo.y, 2.0f));  } else {  pinchZoom = NO;  } } -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {  if(YES == pinchZoom && event.allTouches.count == 2) {  NSArray *touches = [event.allTouches allObjects];  CGPoint pointOne = [[touches objectAtIndex:0] locationInView:self];  CGPoint pointTwo = [[touches objectAtIndex:1] locationInView:self];  //两个手指移动过程中,两点之间距离  CGFloat distance = sqrt(pow(pointOne.x - pointTwo.x, 2.0f) +  pow(pointOne.y - pointTwo.y, 2.0f));  //换算出缩放比例  zoomFactor += (distance - previousDistance) / previousDistance;  zoomFactor = fabs(zoomFactor);  previousDistance = distance;  //缩放  self.layer.transform = CATransform3DMakeScale(zoomFactor, zoomFactor, 1.0f);  } } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {  if(event.allTouches.count != 2) {  pinchZoom = NO;  previousDistance = 0.0f;  } } -(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { } @end 转自:http://www.cnblogs.com/zhw511006/p/3517249.html 

上面实现的方式有一点不足之处就是必须两个手指同时触摸按下才能达到缩放的效果,并不能达到相册里面那样一个手指触摸后,另一个手指按下也可以缩放。如果需要达到和相册照片缩放的效果,需要同时控制begin、move、end几个阶段的事件处理。这个不足就留给感兴趣的同学自己去实现了。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/155056.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • C语言中输入输出所有格式控制符

    C语言中输入输出所有格式控制符title:C语言中输入输出所有格式控制符date:2020-01-1617:02:06description:C语言输入输出的所有格式控制详解C语言中输入输出所有格式控制符 最近在重温C语言,发现C语言的输入输出函数scanf和printf函数在控制输入输出时有许多控制符来控制输入输出数据的格式。于是就打算来整理一下。参考百度百科词条 scanf()是C语言中的一个输入…

    2022年7月24日
    18
  • 增加一行sql(多个左连接查询sql语句)

    sql左,右,内连接转载自:http://323229113.blog.163.com/blog/static/2185362820070172553209/感谢作者.相信做数据分析的朋友,对数据库都比较敏感,作为一名数据分析人员,我们处理数据时总会遇见各种各样的问题,包括连接方式的选择,今天和大家分享一下我眼里的左右连接和内连接的区别.原创博主文章中总结:左连接:保留左边全部行。按左…

    2022年4月17日
    64
  • 使用多重循环打印平行四边形「建议收藏」

    packagecom.qfedu.test1;/*** 使用多重循环打印平行四边形* 当我们打印三角形的时候:* 1.观察第一行符号的个数,第一行符号的个数决定了循环计数器的初始值* 2.观察形状符号的个数是越来越多的话就++越来越少就–* 3.当计数器变化为++的时候判断条件一定要小于或者小于等于某个值相当于设定一个上限* 4.当计数器变化为–的时候判断条件一定要大于或者大于等于某个值相当于设定一个下限*/publicclassT

    2022年4月7日
    75
  • 一批SP名单_SP公司

    一批SP名单_SP公司一批SP名单: 端口号(服务号)SP公司名01007广东嘉讯

    2022年10月4日
    4
  • flex和圣杯布局「建议收藏」

    flex和圣杯布局「建议收藏」flex和圣杯布局

    2022年4月20日
    82
  • psm倾向得分匹配法(倾向性评分匹配)

    原标题:一文读懂倾向得分匹配法(PSM)举例及stata实现(一)一、倾向匹配得分应用之培训对工资的效应政策背景:国家支持工作示范项目(NationalSupportedWork,NSW)研究目的:检验接受该项目(培训)与不接受该项目(培训)对工资的影响。基本思想:分析接受培训组(处理组,treatmentgroup)接受培训行为与不接受培训行为在工资表现上的差异。但是,现实可以观测…

    2022年4月12日
    155

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号