iOS開發UIEvent事件簡介

一、UIEvent簡介html

  UIEvent是表明iOS系統中的一個事件,一個事件包含一個或多個的UITouch數組

  UIEvent分爲四類: UIEventTypesession

typedef NS_ENUM(NSInteger, UIEventType) {
    UIEventTypeTouches,//觸摸事件類型 iOS3.0以後能夠用
    UIEventTypeMotion,//搖晃事件類型 iOS3.0以後能夠用
    UIEventTypeRemoteControl,//遙控事件類型 iOS4.0以後能夠用
    UIEventTypePresses NS_ENUM_AVAILABLE_IOS(9_0),//物理按鈕事件類型 iOS9.0以後能夠用
};

  子事件類型:UIEventSubtypeapp

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,//快進結束【操做:按耳機線控中間按鈕兩下到了快進的位置鬆開】
};

 

二、相關APIdom

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

 

三、觸摸事件示例ide

  相關方法:佈局

- (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);

  拖動和移動效果圖:測試

  代碼展現:atom

//拖動視圖
- (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;
}

 

四、搖晃事件示例url

  相關方法:

- (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;
}

 

五、遙控事件示例

  相關方法:

- (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];
}

 

六、物理按鈕示例

  按壓事件表明了對一個遊戲控制器,蘋果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。
相關文章
相關標籤/搜索