欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS开发之运动事件和远程控制

程序员文章站 2023-11-30 22:41:40
之前我们已经学习了触摸处理和手势识别,其实这两个同属于ios事件的触摸事件,今天我们来学习下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远程控制事件,是通过其他远程设备触发的(比如耳机控制按钮),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

远程控制实例效果

iOS开发之运动事件和远程控制

这次笔记贴了很多代码,是因为这两个事件使用简单,理论知识不多,光讲理论,也不好理解,贴代码非常直观。