iOS开发之运动事件和远程控制
之前我们已经学习了触摸处理和手势识别,其实这两个同属于ios事件的触摸事件,今天我们来学习下ios事件的另外两个事件:
一、运动事件
运动事件,是通过加速器进行触发,和触摸事件一样,继承uiresponder类的对象才能处理运动事件
uiresponder处理运动事件的方法:
#pragma mark 运动开始时执行
- (void)motionbegan:(uieventsubtype)motion withevent:(uievent *)event;
#pragma mark 运动结束后执行
- (void)motionended:(uieventsubtype)motion withevent:(uievent *)event;
#pragma mark 运动被意外取消时执行
- (void)motioncancelled:(uieventsubtype)motion withevent:(uievent *)event;
你没有看错,这里说的运动事件,只是摇晃一下手机而已,所以只有运动开始、运动结束、运动取消,无法取得运动过程中的运动速度、运动方向等数据,这些需要另外的框架去实现,我们可以理解这里的运动时间为 “摆动事件” 。
监听运动事件前提:
监听对象必须成为第一响应者,控件需要- (bool)canbecomefirstresponder方法返回yes
在视图控制器的- (void)viewwillappear:(bool)animated方法中调用运动控件的becomefirstresponder方法,使控件显示时成为第一响应者
在视图控制器的- (void)viewdiddisappear:(bool)animated方法中调用运动控件的resignfirstresponder方法,使控件不显示时注销控件的第一响应者身份
实例:
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
运动事件实例效果
二、远程控制事件
ios远程控制事件,是通过其他远程设备触发的(比如耳机控制按钮),ios远程控制事件相关的只有-(void)remotecontrolreceivedwithevent:(uievent *)event
监听远程控制事件的前提:
启动远程事件接收,调用
[[uiapplication sharedapplication] beginreceivingremotecontrolevents];
ui控件同样要求必须成为第一响应者【使用参考运动事件】
但如果是视图控制器或uiapplication,就没有要求成为第一响应者
应用程序必须是 当前音频额控制者
目前ios7给我们的远程控制权限仅限于音频控制
typedef ns_enum(nsinteger, uieventsubtype) {
// 不包含任何子事件类型
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,
};
实例:
#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:@""];
_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(0, 480, 320, 88)];
view.backgroundcolor = [uicolor lightgraycolor];
view.alpha = 0.9;
[self.view addsubview:view];
//添加播放按钮
_playbutton = [uibutton buttonwithtype:uibuttontypecustom];
_playbutton.bounds = cgrectmake(0, 0, 50, 50);
cgfloat playbtnx = view.frame.size.width/2;
cgfloat playbtny = view.frame.size.height/2;
_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
远程控制实例效果
这次笔记贴了很多代码,是因为这两个事件使用简单,理论知识不多,光讲理论,也不好理解,贴代码非常直观。