首页 技术 正文
技术 2022年11月13日
0 收藏 631 点赞 4,490 浏览 9815 个字

事件处理详解

iOS开发——实用技术OC篇&事件处理详解

一:事件处理

事件处理常见属性:

事件类型

  • @property(nonatomic,readonly) UIEventType     type;
  • @property(nonatomic,readonly) UIEventSubtype  subtype;

事件产生的时间

  • @property(nonatomic,readonly) NSTimeInterval  timestamp;

事件传递

– hitTest:withEvent:

SWIFT

func hitTest(_ point: CGPoint,   withEvent event: UIEvent?) -> UIView?

OBJECTIVE-C

- (UIView *)hitTest:(CGPoint)point          withEvent:(UIEvent *)event

– pointInside:withEvent:

SWIFT

 func pointInside(_ point: CGPoint,        withEvent event: UIEvent?) -> a href="" rel="external nofollow"  Bool /a

OBJECTIVE-C

- (BOOL)pointInside:(CGPoint)pointwithEvent:(UIEvent *)event

事件传递方法的简单实用:

事件传递的时候调用

  • 什么时候调用:当事件传递给控件的时候,就会调用控件的这个方法,去寻找最合适的view
  • 作用:寻找最合适的view

// point:当前的触摸点,point这个点的坐标系就是方法调用者

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {     // 调用系统的做法去寻找最合适的view,返回最合适的view     UIView *fitView = [super hitTest:point withEvent:event]; //    NSLog(@"fitView--%@",fitView);     return fitView; }

// 作用:判断当前这个点在不在方法调用者(控件)上

 - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {     return YES; }

事件传递底层的实现:

如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸事件(掌握)

  1. 如何找到最合适的控件来处理事件?
  2. 自己是否能接收触摸事件?
  3. 触摸点是否在自己身上?
  4. 从后往前遍历子控件数组,重复前面的两个步骤
  5. 如果没有符合条件的子控件,那么就自己最适合处理

// 点击黄色视图 -》 事件 -》 UIApplication -> UIWindow

// 因为所有的视图类都是继承BaseView

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {         NSLog(@"%@--hitTest",[self class]);     //    return [super hitTest:point withEvent:event];     // 1.判断当前控件能否接收事件     if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) return nil;     // 2. 判断点在不在当前控件     if ([self pointInside:point withEvent:event] == NO) return nil;     // 3.从后往前遍历自己的子控件     NSInteger count = self.subviews.count;     ; i >= ; i--) {         UIView *childView = self.subviews[i];         // 把当前控件上的坐标系转换成子控件上的坐标系         CGPoint childP = [self convertPoint:point toView:childView];         UIView *fitView = [childView hitTest:childP withEvent:event];         if (fitView) { // 寻找到最合适的view             return fitView;         }     }     // 循环结束,表示没有比自己更合适的view     return self; }

关于事件传递的底层原理和方法的实现:

事件响应:(响应者链)

响应者链条:是由多个响应者对象连接起来的链条

作用:能很清楚的看见每个响应者之间的联系,并且可以让一个事件多个对象处理。

响应者对象:能处理事件的对象

iOS开发——实用技术OC篇&事件处理详解

事件传递的完整过程

  • 1> 先将事件对象由上往下传递(由父控件传递给子控件),找到最合适的控件来处理这个事件。
  • 2> 调用最合适控件的touches….方法
  • 3> 如果调用了[super touches….];就会将事件顺着响应者链条往上传递,传递给上一个响应者
  • 4> 接着就会调用上一个响应者的touches….方法

重点:如何判断上一个响应者

  • 1> 如果当前这个view是控制器的view,那么控制器就是上一个响应者
  • 2> 如果当前这个view不是控制器的view,那么父控件就是上一个响应者

二:触摸事件

各个方法的解释

iOS开发——实用技术OC篇&事件处理详解

UITouch相关属性:

触摸产生时所处的窗口

  • @property(nonatomic,readonly,retain) UIWindow    *window;

触摸产生时所处的视图

  • @property(nonatomic,readonly,retain) UIView      *view;

短时间内点按屏幕的次数,可以根据tapCount判断单击、双击或更多的点击

  • @property(nonatomic,readonly) NSUInteger          tapCount;

记录了触摸事件产生或变化时的时间,单位是秒

  • @property(nonatomic,readonly) NSTimeInterval      timestamp;

当前触摸事件所处的状态

  • @property(nonatomic,readonly) UITouchPhase        phase;

方法:

  • – (CGPoint)locationInView:(UIView *)view;
  1. 返回值表示触摸在view上的位置
  2. 这里返回的位置是针对view的坐标系的(以view的左上角为原点(0, 0))
  3. 调用时传入的view参数为nil的话,返回的是触摸点在UIWindow的位置
  • – (CGPoint)previousLocationInView:(UIView *)view;

该方法记录了前一个触摸点的位置

UIView不接收触摸事件的三种情况

不接收用户交互

  • userInteractionEnabled = NO

隐藏

  • hidden = YES

透明

  • alpha = 0.0 ~ 0.01

提示:UIImageView的userInteractionEnabled默认就是NO,因此UIImageView以及它的子控件默认是不能接收触摸事件的

实现UIView的拖动:

OC&Swift版

 -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {     UITouch *touch = [touches anyObject];     CGPoint curP = [touch locationInView:self];     CGPoint preP = [touch previousLocationInView:self];     CGFloat offsetX = preP.x - curP.x;     CGFloat offsetY = preP.y - curP.y;     self.transform = CGAffineTransformTranslate(self.transform, -offsetX, -offsetY); }    }

--------------------swift-----------------------

     override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {         var touch:UITouch = touches(AnyObject)         var preP:CGPoint = touch.locationInView(self)         var curP:CGPoint = touch.previousLocationInView(self)         var ofX = curP.x - preP.x         var ofY = curP.y - preP.y         self.transform = CGAffineTransformTranslate(self.transform, ofX, ofY)     }

触摸事件简单介绍:

// 当手指开始触摸view

// NSArray,字典,NSSet(无序)

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {     NSLog(@"%ld", touches.count);     NSLog(@"%s",__func__); }

// 当手指在view上移动的时候

 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {     NSLog(@"%s",__func__); }

// 当手指离开这个view的时候

 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{      NSLog(@"%s",__func__); }

// 当触摸事件被打断的时候调用(电话打入)

 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { }

三:gestureReginazation

各个方法的解释

iOS开发——实用技术OC篇&事件处理详解

UIView拖动

OC&Swift版

 @interface ViewController () @property (weak, nonatomic) IBOutlet iCocosView *dragView; @end @implementation ViewController - (void)viewDidLoad {     [super viewDidLoad]; //    self.view.transform = CGAffineTransformTranslate(self.view.transform, 100, 100);     /**      为对应的View创建并且添加手势和手势监听方法      */     UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(Drag:)];     [self.dragView addGestureRecognizer:pan]; }

/**

*  实现手势监听方法

*/

 -(void)Drag:(UIPanGestureRecognizer *)pan {     //获取盘的位置     CGPoint p = [pan translationInView:pan.view];     /**      *  使用三步法实现赋值      */     //根据pan的位置获取pan的中心点     CGPoint center = pan.view.center;     center.x += p.x;     center.y += p.y;     pan.view.center = center;     //根据pan的移动设置对应View的移动     [pan setTranslation:CGPointZero inView:pan.view]; }

------------------swift-----------------------

  @IBOutlet weak var dragViews: iCocos!     override func viewDidLoad() {         super.viewDidLoad()         var pan:UIPanGestureRecognizer = UIPanGestureRecognizer(target: self, action: "Drag:")         self.dragViews.addGestureRecognizer(pan)     }     func Drag(pan:UIPanGestureRecognizer)     {         var P:CGPoint = pan.translationInView(pan.view!)         var center:CGPoint = pan.view!.center         center.x += P.x         center.y += P.y         pan.view?.center = center         pan.setTranslation(CGPointZero, inView: pan.view)

iOS开发——实用技术OC篇&事件处理详解

------------------------------------------

手势方法简单实用:UIGestureRecognizerDelegate

#pragma mark – 手势代理方法

// 是否允许开始触发手势

 //- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer //{ //    return NO; //}

// 是否允许同时支持多个手势,默认是不支持多个手势

// 返回yes表示支持多个手势

 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {     return YES; }

// 是否允许接收手指的触摸点

 //- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{ //    // 获取当前的触摸点 //    CGPoint curP = [touch locationInView:self.imageView]; //     //    if (curP.x < self.imageView.bounds.size.width * 0.5) { //        return NO; //    }else{ //        return YES; //    } //}

#pragma mark – 点按手势

 - (void)setUpTap {     // 创建点按手势     UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];     tap.delegate = self;     [_imageView addGestureRecognizer:tap]; } - (void)tap:(UITapGestureRecognizer *)tap {     NSLog(@"%s",__func__); }

#pragma mark – 长按手势

 // 默认会触发两次 - (void)setUpLongPress {     UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPress:)];     [self.imageView addGestureRecognizer:longPress]; } - (void)longPress:(UILongPressGestureRecognizer *)longPress {     if (longPress.state == UIGestureRecognizerStateBegan) {         NSLog(@"%s",__func__);     } }

#pragma mark – 清扫

 - (void)setUpSwipe {     // 默认轻扫的方向是往右     UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe)];     swipe.direction = UISwipeGestureRecognizerDirectionUp;     [self.imageView addGestureRecognizer:swipe];     // 如果以后想要一个控件支持多个方向的轻扫,必须创建多个轻扫手势,一个轻扫手势只支持一个方向     // 默认轻扫的方向是往右     UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe)];     swipeDown.direction = UISwipeGestureRecognizerDirectionDown;     [self.imageView addGestureRecognizer:swipeDown]; } - (void)swipe {     NSLog(@"%s",__func__); }

#pragma mark – 旋转手势

 - (void)setUpRotation {     UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotation:)];     rotation.delegate = self;     [self.imageView addGestureRecognizer:rotation]; } // 默认传递的旋转的角度都是相对于最开始的位置 - (void)rotation:(UIRotationGestureRecognizer *)rotation {     self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, rotation.rotation);     // 复位     rotation.rotation = ;     // 获取手势旋转的角度     NSLog(@"%f",rotation.rotation); }

#pragma mark – 捏合

 - (void)setUpPinch {     UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinch:)];     pinch.delegate = self;     [self.imageView addGestureRecognizer:pinch]; } - (void)pinch:(UIPinchGestureRecognizer *)pinch {     self.imageView.transform = CGAffineTransformScale(self.imageView.transform, pinch.scale, pinch.scale);     // 复位     pinch.scale = ; }

#pragma mark – 拖拽

 - (void)setUpPan {     UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];     [self.imageView addGestureRecognizer:pan]; } - (void)pan:(UIPanGestureRecognizer *)pan {     // 获取手势的触摸点     CGPoint curP = [pan locationInView:self.imageView];     // 移动视图     // 获取手势的移动,也是相对于最开始的位置     CGPoint transP = [pan translationInView:self.imageView];     self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, transP.x, transP.y);     // 复位     [pan setTranslation:CGPointZero inView:self.imageView];     NSLog(@"%@",NSStringFromCGPoint(curP)); }

手势状态:

 statetypedef NS_ENUM(NSInteger, UIGestureRecognizerState) {     // 没有触摸事件发生,所有手势识别的默认状态     UIGestureRecognizerStatePossible,     // 一个手势已经开始但尚未改变或者完成时     UIGestureRecognizerStateBegan,     // 手势状态改变     UIGestureRecognizerStateChanged,     // 手势完成     UIGestureRecognizerStateEnded,     // 手势取消,恢复至Possible状态     UIGestureRecognizerStateCancelled,      // 手势失败,恢复至Possible状态     UIGestureRecognizerStateFailed,     // 识别到手势识别     UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded };

四:加速计:(运动)

iOS开发——实用技术OC篇&事件处理详解

iOS开发——实用技术OC篇&事件处理详解

 - (void)orientationChanged:(NSNotification *)notification {      // Respond to changes in device orientation }
 - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {     if (motion == UIEventSubtypeMotionShake)     {         // User was shaking the device. Post a notification named "shake."         [[NSNotificationCenter defaultCenter] postNotificationName:@"shake" object:self];      } }

五:远程控制

iOS开发——实用技术OC篇&事件处理详解

注册:

 MPRemoteCommandCenter *commandCenter = [MPRemoteCommandCenter sharedCommandCenter]; [commandCenter.playCommand addTargetUsingBlock:^(MPRemoteCommandEvent *event) {     // Begin playing the current track.     [[MyPlayer sharedPlayer] play]; }

使用

 - (void)configureNowPlayingInfo:(MPMediaItem*)item{     MPNowPlayingInfoCenter* info = [MPNowPlayingInfoCenter defaultCenter];     NSMutableDictionary* newInfo = [NSMutableDictionary dictionary];     NSSet* itemProperties = [NSSet setWithObjects:MPMediaItemPropertyTitle,           MPMediaItemPropertyArtist,           MPMediaItemPropertyPlaybackDuration,           MPNowPlayingInfoPropertyElapsedPlaybackTime,           nil];     [item enumerateValuesForProperties:itemProperties           usingBlock:^(NSString *property, id value, BOOL *stop) {         [newInfo setObject:value forKey:property];     }];     info.nowPlayingInfo = newInfo; }
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,086
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,561
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,410
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,183
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,820
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,903