你真的了解UIEvent、UITouch吗?
一:首先查看一下关于UIEvent的定义
//事件类型
typedef NS_ENUM(NSInteger, UIEventType) {
UIEventTypeTouches,
UIEventTypeMotion,
UIEventTypeRemoteControl,
}; // 触摸事件的类型
typedef NS_ENUM(NSInteger, UIEventSubtype) { UIEventSubtypeNone = ,
//摇晃
UIEventSubtypeMotionShake = ,
//播放
UIEventSubtypeRemoteControlPlay = ,
//暂停
UIEventSubtypeRemoteControlPause = ,
//停止
UIEventSubtypeRemoteControlStop = ,
//播放和暂停切换
UIEventSubtypeRemoteControlTogglePlayPause = ,
//下一首
UIEventSubtypeRemoteControlNextTrack = ,
//上一首
UIEventSubtypeRemoteControlPreviousTrack = ,
//开始后退
UIEventSubtypeRemoteControlBeginSeekingBackward = ,
//结束后退
UIEventSubtypeRemoteControlEndSeekingBackward = ,
//开始快进
UIEventSubtypeRemoteControlBeginSeekingForward = ,
//结束快进
UIEventSubtypeRemoteControlEndSeekingForward = ,
}; NS_CLASS_AVAILABLE_IOS(2_0) @interface UIEvent : NSObject
//事件类型
@property(nonatomic,readonly) UIEventType type NS_AVAILABLE_IOS(3_0);
// 触摸事件的类型
@property(nonatomic,readonly) UIEventSubtype subtype NS_AVAILABLE_IOS(3_0); //事件的时间戳
@property(nonatomic,readonly) NSTimeInterval timestamp; //所有的触摸
- (nullable NSSet <UITouch *> *)allTouches;
//获得UIWindow的触摸
- (nullable NSSet <UITouch *> *)touchesForWindow:(UIWindow *)window;
//获得UIView的触摸
- (nullable NSSet <UITouch *> *)touchesForView:(UIView *)view;
//获得事件中特定手势的触摸
- (nullable NSSet <UITouch *> *)touchesForGestureRecognizer:(UIGestureRecognizer *)gesture NS_AVAILABLE_IOS(3_2); //会将丢失的触摸放到一个新的 UIEvent 数组中,你可以用 coalescedTouchesForTouch(_:) 方法来访问
- (nullable NSArray <UITouch *> *)coalescedTouchesForTouch:(UITouch *)touch NS_AVAILABLE_IOS(9_0);
//辅助UITouch的触摸,预测发生了一系列主要的触摸事件。这些预测可能不完全匹配的触摸的真正的行为,因为它的移动,所以他们应该被解释为一个估计。
- (nullable NSArray <UITouch *> *)predictedTouchesForTouch:(UITouch *)touch NS_AVAILABLE_IOS(9_0); @end
UIEvent是代表iOS系统中的一个事件,一个事件包含一个或多个的UITouch;UIEvent分为三类:UIEventTypeTouches触摸事件(通过触摸、手势进行触发,例如手指点击、缩放)、UIEventTypeMotion运动事件,通过加速器进行触发(例如手机晃动)、UIEventTypeRemoteControl远程控制事件通过其他远程设备触发(例如耳机控制按钮);
知识点1:在iOS中并不是所有的类都能处理接收并事件,只有继承自UIResponder类的对象才能处理事件,(如我们常用的UIView、UIViewController、UIApplication都继承自UIResponder,它们都能接收并处理事件)。在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;
触摸意外取消时执行(例如正在触摸时打入电话);
运动事件:
(void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event NS_AVAILABLE_IOS(3_0);
运动开始时执行; (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event NS_AVAILABLE_IOS(3_0);
运动结束后执行; (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event NS_AVAILABLE_IOS(3_0);
运动被意外取消时执行;
远程控制事件:
(void)remoteControlReceivedWithEvent:(UIEvent *)event NS_AVAILABLE_IOS(4_0);
接收到远程控制消息时执行;
知识点2:iOS「摇一摇」功能的实现(运动事件的运用)
- (void)viewDidLoad {
[super viewDidLoad];
// 设置允许摇一摇功能
[UIApplication sharedApplication].applicationSupportsShakeToEdit = YES;
// 并让自己成为第一响应者
[self becomeFirstResponder];
return;
} //摇一摇相关方法
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event {
NSLog(@"开始摇动");
return;
} - (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event {
NSLog(@"取消摇动");
return;
} - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
if (event.subtype == UIEventSubtypeMotionShake) { // 判断是否是摇动结束
NSLog(@"摇动结束");
}
return;
}
另外:监听运动事件前提,监听对象必须成为第一响应者;在模拟器中运行时,可以通过「Hardware」-「Shake Gesture」来测试「摇一摇」功能
知识点3:一个摇动随机图片显示的实例(运动事件的运用)
KCImageView.m #import "KCImageView.h" #define kImageCount 3 @implementation KCImageView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.image = [self getImage]; } return self; } #pragma mark 设置控件可以成为第一响应者 - (BOOL)canBecomeFirstResponder{ return YES; } #pragma mark 运动开始 - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{ //这里只处理摇晃事件 if (motion == UIEventSubtypeMotionShake) { self.image = [self getImage]; } } #pragma mark 运动结束 - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event{ } #pragma mark 随机取得图片 - (UIImage *)getImage{ int index = arc4random() % kImageCount; NSString *imageName = [NSString stringWithFormat:@"avatar%i.png",index]; UIImage *image = [UIImage imageNamed:imageName]; return image; } @end KCShakeViewController.m #import "KCShakeViewController.h" #import "KCImageView.h" @interface KCShakeViewController (){ KCImageView *_imageView; } @end @implementation KCShakeViewController - (void)viewDidLoad { [super viewDidLoad]; } #pragma mark 视图显示时让控件变成第一响应者 - (void)viewDidAppear:(BOOL)animated{ _imageView = [[KCImageView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame]; _imageView.userInteractionEnabled = true; [self.view addSubview:_imageView]; [_imageView becomeFirstResponder]; } #pragma mark 视图不显示时注销控件第一响应者的身份 - (void)viewDidDisappear:(BOOL)animated{ [_imageView resignFirstResponder]; } @end
知识点4:远程控制事件的运用
iOS远程控制事件,是通过其他远程设备触发的(比如耳机控制按钮),iOS远程控制事件相关的只有-(void)remoteControlReceivedWithEvent:(UIEvent *)event;监听远程控制事件的前提:启动远程事件接收,调用[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];UI控件同样要求必须成为第一响应者【使用参考运动事件】,但如果是视图控制器或UIApplication,就没有要求成为第一响应者,应用程序必须是 当前音频额控制者,目前iOS7给我们的远程控制权限仅限于音频控制;
一个关于音乐远程控制实例:
#import "ViewController.h" @interface ViewController (){ UIButton *_playButton; BOOL _isPlaying; } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; [self initLayout]; } - (BOOL)canBecomeFirstResponder{ return NO; } - (void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; NSURL *url = [NSURL URLWithString:@"http://stream.jewishmusicstream.com:8000"]; _player = [[AVPlayer alloc] initWithURL:url]; } #pragma mark 远程控制事件 - (void)remoteControlReceivedWithEvent:(UIEvent *)event{ if(event.type == UIEventTypeRemoteControl){ switch (event.subtype) { case UIEventSubtypeRemoteControlPlay: [_player play]; _isPlaying = true; break; case UIEventSubtypeRemoteControlTogglePlayPause: [self btnClick:_playButton]; break; case UIEventSubtypeRemoteControlNextTrack: NSLog(@"Next..."); break; case UIEventSubtypeRemoteControlPreviousTrack: NSLog(@"Previous..."); break; case UIEventSubtypeRemoteControlBeginSeekingForward: NSLog(@"Begin seek forward..."); break; case UIEventSubtypeRemoteControlEndSeekingForward: NSLog(@"End seek forward..."); break; case UIEventSubtypeRemoteControlBeginSeekingBackward: NSLog(@"Begin seek backward..."); break; case UIEventSubtypeRemoteControlEndSeekingBackward: NSLog(@"End seek backward..."); break; default: break; } [self changeUIState]; } } #pragma mark 界面布局 - (void)initLayout{ //专辑封面 UIImage *image = [UIImage imageNamed:@"wxl.jpg"]; CGRect *frame = [UIScreen mainScreen].applicationFrame; UIImageView *imageView = [[UIImageView alloc] initWithFrame:frame]; imageView.image = image; imageView.contentMode = UIViewContentModeScaleAspectFill; [self.view addSubview:imageView]; //播放控制面板 UIView *view = [[UIView alloc] initWithFrame:CGRectMake(, , , )]; view.backgroundColor = [UIColor lightGrayColor]; view.alpha = 0.9; [self.view addSubview:view]; //添加播放按钮 _playButton = [UIButton buttonWithType:UIButtonTypeCustom]; _playButton.bounds = CGRectMake(, , , ); CGFloat playBtnX = view.frame.size.width/; CGFloat playBtnY = view.frame.size.height/; _playButton.center = CGPointMake(playBtnX, playBtnY); [self changeUIState]; [_playButton addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside]; [view addSubview:_playButton]; } #pragma mark 界面状态 - (void)changeUIState{ if(_isPlaying){ UIImage *pauseImage = [UIImage imageNamed:@"playing_btn_pause_n.png"]; UIImage *pauseImageH = [UIImage imageNamed:@"playing_btn_pause_h.png"]; [_playButton setImage:pauseImage forState:UIControlStateNormal]; [_playButton setImage:pauseImageH forState:UIControlStateHighlighted]; }else{ UIImage *playImage = [UIImage imageNamed:@"playing_btn_play_n.png"]; UIImage *playImageH = [UIImage imageNamed:@"playing_btn_play_h.png"]; [_playButton setImage:playImage forState:UIControlStateNormal]; [_playButton setImage:playImageH forState:UIControlStateHighlighted]; } } - (void)btnClick:(UIButton *)btn{ if (_isPlaying) { [_player pause]; }else{ [_player play]; } _isPlaying =! _isPlaying; [self changeUIState]; } @end
二:首先查看一下关于UITouch的定义
//触摸事件在屏幕上有一个周期
typedef NS_ENUM(NSInteger, UITouchPhase) {
UITouchPhaseBegan, //开始触摸
UITouchPhaseMoved, //移动
UITouchPhaseStationary, //停留
UITouchPhaseEnded, //触摸结束
UITouchPhaseCancelled, //触摸中断
}; //检测是否支持3DTouch
typedef NS_ENUM(NSInteger, UIForceTouchCapability) {
UIForceTouchCapabilityUnknown = , //3D Touch检测失败
UIForceTouchCapabilityUnavailable = , //3D Touch不可用
UIForceTouchCapabilityAvailable = //3D Touch可用
}; NS_CLASS_AVAILABLE_IOS(2_0) @interface UITouch : NSObject //触摸产生或变化的时间戳 只读
@property(nonatomic,readonly) NSTimeInterval timestamp;
//触摸周期内的各个状态
@property(nonatomic,readonly) UITouchPhase phase;
//短时间内点击的次数 只读
@property(nonatomic,readonly) NSUInteger tapCount; //获取手指与屏幕的接触半径 IOS8以后可用 只读
@property(nonatomic,readonly) CGFloat majorRadius NS_AVAILABLE_IOS(8_0);
//获取手指与屏幕的接触半径的误差 IOS8以后可用 只读
@property(nonatomic,readonly) CGFloat majorRadiusTolerance NS_AVAILABLE_IOS(8_0); //触摸时所在的窗口 只读
@property(nullable,nonatomic,readonly,strong) UIWindow *window;
//触摸时所在视图
@property(nullable,nonatomic,readonly,strong) UIView *view;
//获取触摸手势
@property(nullable,nonatomic,readonly,copy) NSArray <UIGestureRecognizer *> *gestureRecognizers NS_AVAILABLE_IOS(3_2); //取得在指定视图的位置
// 返回值表示触摸在view上的位置
// 这里返回的位置是针对view的坐标系的(以view的左上角为原点(0,0))
// 调用时传入的view参数为nil的话,返回的是触摸点在UIWindow的位置
- (CGPoint)locationInView:(nullable UIView *)view;
//该方法记录了前一个触摸点的位置
- (CGPoint)previousLocationInView:(nullable UIView *)view; //获取触摸压力值,一般的压力感应值为1.0 IOS9 只读
@property(nonatomic,readonly) CGFloat force NS_AVAILABLE_IOS(9_0); //获取最大触摸压力值
@property(nonatomic,readonly) CGFloat maximumPossibleForce NS_AVAILABLE_IOS(9_0); @end
知识点1:触摸时,图片移动(实例)
- (void)viewDidLoad
{
UIImageView *image = [[UIImageView alloc] initWithFrame:CGRectMake(20.0, 50.0, 45.0, 45.0)];
image.image = [UIImage imageNamed:@"baby.png"];
image.tag = ;
[self.view addSubview:image]; [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
} -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
UIImageView *view1 = (UIImageView*)[self.view viewWithTag:];
CGPoint point = [touch locationInView:self.view];
CGRect frame = view1.frame;
frame.origin = point;
view1.frame = frame;
}
知识点2:创建可以拖动的视图
CGPoint originalLocation;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
originalLocation = [touch locationInView:self.view];
} -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint currentLocation = [touch locationInView:self.view];
CGRect frame = self.view.frame;
frame.origin.x += currentLocation.x-originalLocation.x;
frame.origin.y += currentLocation.y-originalLocation.y;
self.view.frame = frame;
}
这里先在touchesBegan中通过[touch locationInView:self.view]获取手指触摸在当前视图上的位置,用CGPoint变量记录,然后在手指移动事件touchesMoved方法中获取触摸对象当前位置,并通过于与原始位置的差值计算出移动偏移量,再设置当前视图的位置。
你真的了解UIEvent、UITouch吗?的更多相关文章
- iOS开发——UI进阶篇(十二)事件处理,触摸事件,UITouch,UIEvent,响应者链条,手势识别
触摸事件 在用户使用app过程中,会产生各种各样的事件 一.iOS中的事件可以分为3大类型 触摸事件加速计事件远程控制事件 响应者对象在iOS中不是任何对象都能处理事件,只有继承了UIResponde ...
- UIResponder NSSet UITouch UIEvent
UIResponder: UIView的超类,用来响应handle(触屏.motion.响应者等)事件. NSSet:一系列的类集合(类似数组). UITouch:一个点击类.负责:点击的view,w ...
- iOS:触摸控件UITouch、事件类UIEvent
UITouch:触摸控件类 UIEvent:事件类 ❤️❤️❤️UITouch的介绍❤️❤️❤️ 一.触摸状态类型枚举 typedef NS_ENUM(NSInteger, UITouchPhas ...
- 你真的了解UIScrollView吗?
一:首先查看一下关于UIScrollView的定义 NS_CLASS_AVAILABLE_IOS(2_0) @interface UIScrollView : UIView <NSCoding& ...
- 你真的了解UIControl吗?
一:首先查看一下关于UIControl的定义 NS_CLASS_AVAILABLE_IOS(2_0) @interface UIControl : UIView //控件默认是启用的YES.是否要禁用 ...
- 你真的了解UIResponder吗?
1:首先查看一下关于UIResponder的定义 NS_CLASS_AVAILABLE_IOS(2_0) @interface UIResponder : NSObject //响应链中负责传递事件的 ...
- iOS - UITouch
前言 NS_CLASS_AVAILABLE_IOS(2_0) @interface UITouch : NSObject @available(iOS 2.0, *) public class UIT ...
- UITouch的用法
UITouch一般无法直接获取,是通过UIView的touchesBegan等函数获得. //这四个方法是UIResponder中得方法 // Generally, all responders wh ...
- 触摸事件UITouch的用法
触摸屏幕是iOS设备接受用户输入的主要方式,包括单击.双击.拨动以及多点触摸等,这些操作都会产生触摸事件. 在Cocoa中,代表触摸对象的类是UITouch.当用户触摸屏幕后,就会产生相应的事件,所有 ...
随机推荐
- Go语言接口
接口是面向对象的必备属性之一,即便是像C语言这种面向过程的语言也可以通过指向函数的指针来实现接口.我们熟知的面向对象语言中更是少不了接口.最近闲了下来,又可以开始学习Go语言了,发现Go语言的接口吸收 ...
- ROS 新手常见问题汇总
版权声明:本文为博主原创文章,转载请标明出处: http://www.cnblogs.com/liu-fa/p/5772469.html 该博文致力于汇总ROS常见问题及解答,让更多的人少走弯路,避免 ...
- 【视频处理】YUV格式说明
YUV,是一种颜色编码方法,Y表示明亮度(Luminance.Luma),U和V则是色度.浓度(Chrominance.Chroma). YUV,Y`UV,YCbCr,YPbPr等都可以称为YUV,彼 ...
- C#2.0 to 4.0
//xmlElement.set_InnerText(value); xmlElement.InnerText = value; ).ToCharArray());//Convert.ToChar(s ...
- Razor语法的一些特殊需求输出
开发ASP.NET MVC,常会使用Razor来呈现内容.下面有几个特殊需求的输出,Insus.NET列出来让大家参考. 双@@输出只有一个. 在Razor的语法中,如果想输出html,它会有两种语法 ...
- 国产达梦数据库的结合Enterprise Library的应用开发
在上篇<基于Enterprise Library的Winform开发框架实现支持国产达梦数据库的扩展操作>介绍了如何在Enterprise Library的数据访问层上支持这种神秘的国产数 ...
- Abot 爬虫分析-整体结构
1. 引言 在Github 上搜索下Web Crawler 有上千个开源的项目,但是C#的仅仅只有168 个,相比于Java 或者Python 确实少的可怜.如果按照Stars 排名.可以看到 排在第 ...
- maven url
aliyun阿里云Maven仓库地址--加速你的maven构建 maven仓库用过的人都知道,国内有多么的悲催.还好有比较好用的镜像可以使用,尽快记录下来.速度提升100倍. http://mav ...
- linux 查找目录或文件详解
查找目录:find /(查找范围) -name '查找关键字' -type d查找文件:find /(查找范围) -name 查找关键字 -print 如果需要更进一步的了解,可以参看Linux的命令 ...
- MongoDB常用操作--数据库
1.查看所有数据库,使用命令 show dbs 2.查看当前所在数据库,使用命令 db 3. 查看当前数据库中所有的集合,使用命令 show collections 或使用show tables 4. ...