• iOS开发UIEvent事件简介


    1、UIEvent简介

      UIEvent是代表iOS系统中的一个事件,一个事件包含一个或多个的UITouch

      UIEvent分为四类: UIEventType

    typedef NS_ENUM(NSInteger, UIEventType) {
        UIEventTypeTouches,//触摸事件类型 iOS3.0之后可以用
        UIEventTypeMotion,//摇晃事件类型 iOS3.0之后可以用
        UIEventTypeRemoteControl,//遥控事件类型 iOS4.0之后可以用
        UIEventTypePresses NS_ENUM_AVAILABLE_IOS(9_0),//物理按钮事件类型 iOS9.0之后可以用
    };

      子事件类型:UIEventSubtype

    typedef NS_ENUM(NSInteger, UIEventSubtype) {
        //事件没有子类型 iOS3.0之后可以用
        UIEventSubtypeNone                              = 0,
        
        //事件子类型晃动的设备 iOS3.0之后可以用
        UIEventSubtypeMotionShake                       = 1,
        
        //遥控的事件子类型 iOS4.0之后可以用
        UIEventSubtypeRemoteControlPlay                 = 100,//播放
        UIEventSubtypeRemoteControlPause                = 101,//暂停
        UIEventSubtypeRemoteControlStop                 = 102,//停止
        UIEventSubtypeRemoteControlTogglePlayPause      = 103,//播放和暂停之间切换【操作:播放或暂停状态下,按耳机线控中间按钮一下】
        UIEventSubtypeRemoteControlNextTrack            = 104,//下一曲【操作:按耳机线控中间按钮两下】
        UIEventSubtypeRemoteControlPreviousTrack        = 105,//上一曲【操作:按耳机线控中间按钮三下】
        UIEventSubtypeRemoteControlBeginSeekingBackward = 106,//快退开始【操作:按耳机线控中间按钮三下不要松开】
        UIEventSubtypeRemoteControlEndSeekingBackward   = 107,//快退结束【操作:按耳机线控中间按钮三下到了快退的位置松开】
        UIEventSubtypeRemoteControlBeginSeekingForward  = 108,//快进开始【操作:按耳机线控中间按钮两下不要松开】
        UIEventSubtypeRemoteControlEndSeekingForward    = 109,//快进结束【操作:按耳机线控中间按钮两下到了快进的位置松开】
    };

    2、相关API

    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;//事件发生时间
    
    //返回与接收器相关联的所有触摸对象。
    #if UIKIT_DEFINE_AS_PROPERTIES
    @property(nonatomic, readonly, nullable) NSSet <UITouch *> *allTouches;
    #else
    - (nullable NSSet <UITouch *> *)allTouches;
    #endif
    - (nullable NSSet <UITouch *> *)touchesForWindow:(UIWindow *)window;//返回属于一个给定视图的触摸对象,用于表示由接收器所表示的事件。
    - (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

    3、触摸事件示例

      相关方法:

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
    - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
    - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
    - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
    - (void)touchesEstimatedPropertiesUpdated:(NSSet<UITouch *> *)touches NS_AVAILABLE_IOS(9_1);

      拖动和移动效果图:

      代码展示:

    //拖动视图
    - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        UITouch *touch = [touches anyObject];
        CGPoint currPoint = [touch locationInView:self.view];
        CGPoint prePoint = [touch previousLocationInView:self.view];
        CGRect frame = self.btnView.frame;
        frame.origin.x += currPoint.x -prePoint.x;
        frame.origin.y += currPoint.y -prePoint.y;
        self.btnView.frame = frame;
    }
    
    //点击移动
    - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        UITouch *touch = [touches anyObject];
        CGRect frame = self.btnView.frame;
        frame.origin = [touch locationInView:self.view];
        self.btnView.frame = frame;
    }

    4、摇晃事件示例

      相关方法:

    - (void)motionBegan:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0);
    - (void)motionEnded:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0);
    - (void)motionCancelled:(UIEventSubtype)motion withEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(3_0);

      效果图:模拟器摇一摇「Hardware」-「Shake Gesture」来测试 ,快捷键:command+control+z

      摇一摇显示随机图片:

    @implementation MotionImageView
    - (instancetype)initWithFrame:(CGRect)frame{
        self = [super initWithFrame:frame];
        if (self) {
            self.image = [self getImage];
        }
        return self;
    }
    
    - (BOOL)canBecomeFirstResponder{
        return YES;
    }
    
    - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{
        if (motion == UIEventSubtypeMotionShake) {
            self.image = [self getImage];
        }
    }
    - (UIImage *)getImage{
        int index = arc4random() % 5+1;
        NSString *imageName = [NSString stringWithFormat:@"pic%i.png",index];
        UIImage *image = [UIImage imageNamed:imageName];
        return image;
        
    }
    @end

      在ViewController中使用:

    //成为第一响应者
    - (void)viewDidAppear:(BOOL)animated{
        [self.imageView becomeFirstResponder];
    }
    //注销第一响应者
    - (void)viewDidDisappear:(BOOL)animated{
        [self.imageView resignFirstResponder];
    }
    //支持摇一摇功能
    - (void)viewDidLoad {
        [super viewDidLoad];
        [UIApplication sharedApplication].applicationSupportsShakeToEdit = YES;
    }

    5、遥控事件示例

      相关方法:

    - (void)remoteControlReceivedWithEvent:(nullable UIEvent *)event NS_AVAILABLE_IOS(4_0);

      代码实现:

    #import "VideoViewController.h"
    #import <AVFoundation/AVFoundation.h>
    @interface VideoViewController ()
    {
        UIButton *_playButton;
        BOOL _isPlaying;
        AVPlayer    *_player;
    }
    @end
    
    @implementation VideoViewController
    
    - (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://music.163.com/song/media/outer/url?id=1293886117.mp3"];
        _player = [[AVPlayer alloc] initWithURL:url];
    }
    
    #pragma mark 远程控制事件
    - (void)remoteControlReceivedWithEvent:(UIEvent *)event{
        if(event.type == UIEventTypeRemoteControl){
            switch (event.subtype) {
                case UIEventSubtypeRemoteControlPlay:
                    [_player play];
                    _isPlaying = true;
                    NSLog(@"播放");
                    break;
                case UIEventSubtypeRemoteControlTogglePlayPause:
                    [self btnClick:_playButton];
                    NSLog(@"播放和暂停之间切换【操作:播放或暂停状态下,按耳机线控中间按钮一下】");
                    break;
                case UIEventSubtypeRemoteControlNextTrack:
                    NSLog(@"下一曲【操作:按耳机线控中间按钮两下】");
                    break;
                case UIEventSubtypeRemoteControlPreviousTrack:
                    NSLog(@"上一曲【操作:按耳机线控中间按钮三下】");
                    break;
                case UIEventSubtypeRemoteControlBeginSeekingForward:
                    NSLog(@"快进开始【操作:按耳机线控中间按钮两下不要松开】");
                    break;
                case UIEventSubtypeRemoteControlEndSeekingForward:
                    NSLog(@"快进结束【操作:按耳机线控中间按钮两下到了快进的位置松开】");
                    break;
                case UIEventSubtypeRemoteControlBeginSeekingBackward:
                    NSLog(@"快退开始【操作:按耳机线控中间按钮三下不要松开】");
                    break;
                case UIEventSubtypeRemoteControlEndSeekingBackward:
                    NSLog(@"快退结束【操作:按耳机线控中间按钮三下到了快退的位置松开】");
                    break;
                case UIEventSubtypeRemoteControlStop:
                    NSLog(@"停止");
                    break;
                case UIEventSubtypeRemoteControlPause:
                    NSLog(@"暂停");
                    break;
                default:
                    break;
            }
            [self changeUIState];
        }
        
    }
    
    #pragma mark 界面布局
    - (void)initLayout{
        //专辑封面
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
        imageView.image = [UIImage imageNamed:@"pic1.jpg"];
        imageView.contentMode = UIViewContentModeScaleAspectFill;
        [self.view addSubview:imageView];
        
        //播放控制面板
        UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 480, [UIScreen mainScreen].bounds.size.width, 88)];
        view.backgroundColor = [UIColor yellowColor];
        view.alpha = 0.9;
        [self.view addSubview:view];
        
        //添加播放按钮
        _playButton = [UIButton buttonWithType:UIButtonTypeCustom];
        _playButton.bounds = CGRectMake(0, 0, 50, 50);
        _playButton.center = CGPointMake(CGRectGetWidth(view.frame)/2,CGRectGetHeight(view.frame)/2);
        [self changeUIState];
        [_playButton addTarget:self
                        action:@selector(btnClick:)
              forControlEvents:UIControlEventTouchUpInside];
        [view addSubview:_playButton];
        
    }
    
    #pragma mark 界面状态
    - (void)changeUIState{
        if(_isPlaying){
            UIImage *pauseImage = [UIImage imageNamed:@"pic2.png"];
            [_playButton setImage:pauseImage forState:UIControlStateNormal];
        }else{
            UIImage *playImage = [UIImage imageNamed:@"pic3.png"];
            [_playButton setImage:playImage forState:UIControlStateNormal];
        }
    }
    
    - (void)btnClick:(UIButton *)btn{
        if (_isPlaying) {
            [_player pause];
        }else{
            [_player play];
        }
        _isPlaying =! _isPlaying;
        [self changeUIState];
    }
    @end
    线控代码实现

      号外1:获取网易云mp3路径

      号外2:后台播放音乐

    - (void)applicationWillResignActive:(UIApplication *)application {
        [[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
        AVAudioSession *session = [AVAudioSession sharedInstance];
        [session setActive:YES error:nil];
        [session setCategory:AVAudioSessionCategoryPlayback error:nil];
    }

    6、物理按钮示例

      按压事件代表了对一个游戏控制器,苹果TV远程,或其他有物理按钮的设备之间的交互。;

      所以对于iPhone的手机而言在没有物理按键连接的情况下,是无法触发该事件的;

       相关方法:

    //物理按钮 深按API,一般用于遥控器
    - (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);// 开始按压的时候调用
    - (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);// 按压改变的时候调用
    - (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);// 按压结束的时候调用
    - (void)pressesCancelled:(NSSet<UIPress *> *)presses withEvent:(nullable UIPressesEvent *)event NS_AVAILABLE_IOS(9_0);// 当系统发出取消按压事件的时候调用

      UIPress相关API

    NS_ENUM_AVAILABLE_IOS(9_0) typedef NS_ENUM(NSInteger, UIPressPhase) {
        UIPressPhaseBegan,         // 开始
        UIPressPhaseChanged,       // 变化
        UIPressPhaseStationary,    // 按下不动时
        UIPressPhaseEnded,         // 结束
        UIPressPhaseCancelled,     // 取消
    };
    
    NS_ENUM_AVAILABLE_IOS(9_0) typedef NS_ENUM(NSInteger, UIPressType) {
        UIPressTypeUpArrow,     //向上的键被按压
        UIPressTypeDownArrow,   //向下的键被按压
        UIPressTypeLeftArrow,   //向左的键被按压
        UIPressTypeRightArrow,  //向右的键被按压
        
        UIPressTypeSelect,      //选择 的键被按压
        UIPressTypeMenu,        //菜单 的键被按压
        UIPressTypePlayPause,   //播放/暂停 的键被按压
    };
    
    NS_CLASS_AVAILABLE_IOS(9_0) @interface UIPress : NSObject
    
    @property(nonatomic,readonly) NSTimeInterval   timestamp;   //时间
    @property(nonatomic,readonly) UIPressPhase     phase;       //按下阶段
    @property(nonatomic,readonly) UIPressType      type;        //按下的类型
    
    @property(nullable,nonatomic,readonly,strong) UIWindow                        *window; //所处视图
    @property(nullable,nonatomic,readonly,strong) UIResponder                     *responder;//
    @property(nullable,nonatomic,readonly,copy)   NSArray <UIGestureRecognizer *> *gestureRecognizers;//手势
    
    @property(nonatomic, readonly) CGFloat force; //按钮按压的力 返回一个介于0和1之间的值。数字按钮返回0或1。

      

  • 相关阅读:
    GO-GRPC实践(二) 增加拦截器,实现自定义context(带request_id)、recover以及请求日志打印
    第六章-堆
    第五章-本地方法接口和本地方法栈
    第四章-虚拟机栈
    第三章-运行时数据区及程序计数器
    04-再谈类的加载器
    03-类的加载过程(类的生命周期)详解
    1.编程入门
    SpringBoot 整合 SpringSecurity 梳理
    pip版本过低无法升级问题
  • 原文地址:https://www.cnblogs.com/xianfeng-zhang/p/9469629.html
Copyright © 2020-2023  润新知