一、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。