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)
上一篇 2022年7月3日 下午10:16
下一篇 2022年7月3日 下午10:16


相关推荐

  • 微信开发者工具程序开发好后,不报错,但是黑屏「建议收藏」

    微信开发者工具程序开发好后,不报错,但是黑屏「建议收藏」微信开发者工具程序开发好后,不报错,但是黑屏

    2022年4月24日
    55
  • android attributeset 工具类,android attributeset总结

    android attributeset 工具类,android attributeset总结一般是当项目中遇到这样的场景需要自定义控件的 AttributeSet 属性 一个自定义控件的有些属性内容是随着外部条件而动态改变的 forexample 一个自定义的 ListView 控件 需要在底部添加一个 View 而这个 View 在不同的模块使用中传入的 View 是不同的 这时候有两种方法 一种方法就是在自定义 ListView 控件类中提供一个公开的接口给外部调用从而将 View 动态的传入进去 另外一种

    2026年3月19日
    2
  • sdfsdfsd_dsd cd

    sdfsdfsd_dsd cd1)—为DataSnap系统服务程序添加描述这几天一直在研究Delphi2010的DataSnap,感觉功能真是很强大,现在足有理由证明Delphi7该下岗了。DataSnap有三种服务模式,其中ServiceApplication方式建立的windows服务没有描述,描述部分是空的,感觉总是欠缺点什么。现找到办法添加描述:procedureTServerContainer2

    2022年10月4日
    7
  • 计算机硬件组成

    计算机硬件组成1 计算机硬件由两大部分组成 主机和外设主机包括 cpu 内存外设包括 输入设备 输出设备 辅助存储器具体的硬件 cpu 内存 硬盘 主板 电源 风扇 网卡 前面这些是重要的 显示器 键盘 鼠标 声卡 显卡 这些是不重要的 下面来一一介绍 Cpu 中央处理器 centralproce 作用 运算和控制相当于人的大脑了解 CPU 核数 四核心双核心六核心八核心

    2026年3月17日
    2
  • H5音乐标签实现网页自动播放和隐藏

    H5音乐标签实现网页自动播放和隐藏网页播放音乐如果不能自动播放,用iframe放在body最下面。即可运行。<iframesrc=”no.mp3″allow=”autoplay”hidden/>

    2022年7月25日
    23
  • Redis的相关问题总结

    Redis的相关问题总结

    2021年11月7日
    44

发表回复

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

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