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几个阶段的事件处理。这个不足就留给感兴趣的同学自己去实现了。

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 关闭对话框,OnClose和OnCancel

    关闭对话框,OnClose和OnCancel

  • python 打包exe文件[通俗易懂]

    上一篇说了我自己做了一个定时截屏的工具,我想如果我可以打包成exe文件,那我就可以单独放在桌面运行,不用进入程序启动运行就可以完成截屏工作了。安装模块1、pyinstaller这里建议最好使用命令安装,手动下载安装有很多其他的模块不存在,我就一开始是手动安装,安装一次缺一个模块,然后补一个,然后又少一个,命令行安装就没这个问题了pipinstallpyinstaller2、pyQt…

  • [USACO12JAN]视频游戏的连击Video Game Combos「建议收藏」

    很早之前就做过啦补一下题解F(i,j)前i个的字符为j的匹配注意end要累加#include&lt;iostream&gt;#include&lt;cstdio&gt;#include&lt;cstring&gt;#include&lt;cmath&gt;#include&lt;algorithm&gt;#include&lt;queue&gt;usingnam…

  • mysql的innodb与myisam(oracle主键和唯一索引的区别)

    InnoDB和MyISAM是很多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,5.7之后就不一样了1、事务和外键InnoDB具有事务,支持4个事务隔离级别,回滚,崩溃修复能力和多版本并发的事务安全,包括ACID。如果应用中需要执行大量的INSERT或UPDATE操作,则应该使用InnoDB,这样可以提高多用户并发操作的性能MyISAM管理非事务表。它提供高速存储和检索,以及全文搜索…

  • svn用户名和密码设置_git配置本地用户名密码

    svn用户名和密码设置_git配置本地用户名密码SVN配置用户192.168.1.200   Administrator     ydd!@#$1234()90 1、备份D:\svn\conf\authz,再修改2、备份D:\svn\conf\passwd,再修改注意:* 权限配置文件中出现的用户名必须已在用户配置文件中定义。* 对权限配置文件的修改立即生效,不必重启s

  • hashmap面试题简书_三年php面试题

    hashmap面试题简书_三年php面试题这篇文章仅限小编个人的理解,小编不是Java方向的,只是对Java有很高的学习兴趣如果有什么不对的地方还望大佬指点HashMap的底层是数组+链表,(很多人应该都知道了)JDK1.7的是数组+链表(1.7只是一个例子,以前的话也是这样后面就以1.7为例子了)首先是一个数组,然后数组的类型是链表元素是头插法JDK1.8的是数组+链表或者数组+红黑树首先是一个数组,然后数组的类型是链表在链表的元素大于8的时候,会变成红黑树在红黑树的元素小于6的时候会变成链表元素进行尾插HaspM.

发表回复

您的电子邮箱地址不会被公开。

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