iOS DevelopmentiOS学习开发iOS开发技术分享

检测屏幕旋转(通知和传感器方式)

2016-03-16  本文已影响668人  KavinZhou
监测屏幕横竖屏
方法一: 发通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientChange:)name:UIDeviceOrientationDidChangeNotification object:nil];

也可以用下面这种通知

    UIDevice *device = [UIDevice currentDevice]; 
    [device beginGeneratingDeviceOrientationNotifications]; //调用设备的加速度信息获取
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; 
    [nc addObserver:self selector:@selector(orientChange:)name:UIDeviceOrientationDidChangeNotification  object:device];

然后在orientChange:中使用下面的枚举判断屏幕旋转即可

UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
/*
 UIDeviceOrientationUnknown,
 UIDeviceOrientationPortrait,            // Device oriented vertically, home button on the bottom
 UIDeviceOrientationPortraitUpsideDown,  // Device oriented vertically, home button on the top
 UIDeviceOrientationLandscapeLeft,       // Device oriented horizontally, home button on the right
 UIDeviceOrientationLandscapeRight,      // Device oriented horizontally, home button on the left
 UIDeviceOrientationFaceUp,              // Device oriented flat, face up
 UIDeviceOrientationFaceDown
 */
方法二: 使用传感器

1, 上面的通知的方法的硬伤就是, 如果用户锁定了设备的竖屏(不少用户这么干), 那么通知就会失效了. 控制器根本不会通过通知获取任何关于屏幕旋转的信息.
2, 解决方法就是利用设备的传感器. 传感器不会说谎. 下面就把整个实现贴出来
几个步骤下面的注释已经很详尽. 需要说明的是, 我是采用了DeviceMotion这个方法来获取传感器的信息. 是通过重力感应来实现的. 当然, 用加速器Accelerometer来获取屏幕旋转信息. 都是可以的

#import <CoreMotion/CoreMotion.h>
@interface
// 1,首先 拥有一个全局的CMMotionManager对象
@property (nonatomic, strong) CMMotionManager *motionManager;

@implementation
// 2, 调用这个方法, 开启屏幕旋转监测
- (void)startMotionManager{
    if (_motionManager == nil) {
        _motionManager = [[CMMotionManager alloc] init];
    }
    // 刷新数据频率
    _motionManager.deviceMotionUpdateInterval = 1/15.0;
  
  // 判断设备的传感器是否可用
    if (_motionManager.deviceMotionAvailable) {
        NSLog(@"Device Motion Available");
        [_motionManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue]
                                            withHandler: ^(CMDeviceMotion *motion, NSError*error){
                                                [selfperformSelectorOnMainThread:@selector(handleDeviceMotion:) withObject:motionwaitUntilDone:YES];
                                                
                                            }];
    } else {
        NSLog(@"No device motion on device.");
        [self setMotionManager:nil];
    }
}

- (void)handleDeviceMotion:(CMDeviceMotion *)deviceMotion{
    double x = deviceMotion.gravity.x;
    double y = deviceMotion.gravity.y;
    if (fabs(y) >= fabs(x))
    {
        if (y >= 0){
            // UIDeviceOrientationPortraitUpsideDown;
        }
        else{
            // UIDeviceOrientationPortrait;
        }
    }
    else
    {
        if (x >= 0){
            // UIDeviceOrientationLandscapeRight;
            DLOG(@"右旋转");

        }
        else{
            // UIDeviceOrientationLandscapeLeft;
            DLOG(@"左旋转");
        }
    }
}
关闭时调用
  [_motionManager stopDeviceMotionUpdates];
手动旋转设备
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];

// 防止方法频繁调用
- (void)handleDeviceMotion:(CMDeviceMotion *)deviceMotion {
    double x = deviceMotion.gravity.x;
    double y = deviceMotion.gravity.y;
    
    static BOOL portraitFlag_ = false;
    static BOOL landscapeLeftFlag_ = false;
    static BOOL landscapeRightFlag_ = false;
    static BOOL upsideDownFlag_ = false;
    
    if (fabs(y) >= fabs(x)) {
        if (y < 0) {
            if (portraitFlag_) {
                return;
            }
            DLOG(@"竖屏");
            portraitFlag_ = true;
            landscapeLeftFlag_ = false;
            landscapeRightFlag_ = false;
            upsideDownFlag_ = false;
        }
        else {
            if (upsideDownFlag_) {
                return;
            }
            DLOG(@"倒屏");
            portraitFlag_ = false;
            landscapeLeftFlag_ = false;
            landscapeRightFlag_ = false;
            upsideDownFlag_ = true;
        }
    }
    else {
        if (x < 0) {
            if (landscapeLeftFlag_) {
                return;
            }
            DLOG(@"左旋转");
            portraitFlag_ = false;
            landscapeLeftFlag_ = true;
            landscapeRightFlag_ = false;
            upsideDownFlag_ = false;
        }
        else {
            if (landscapeRightFlag_) {
                return;
            }
            DLOG(@"右旋转");
            portraitFlag_ = false;
            landscapeLeftFlag_ = false;
            landscapeRightFlag_ = true;
            upsideDownFlag_ = false;
        }
    }
}

参考
http://stackoverflow.com/questions/11773088/uideviceorientationdidchangenotification-event-not-firing-when-user-disable-scre

startMotionManager方法中实现

    if (_motionManager.accelerometerAvailable) {
        [_motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMAccelerometerData * _Nullable accelerometerData, NSError * _Nullable error) {
            [self performSelectorOnMainThread:@selector(handleAccelerometer:) withObject:accelerometerData waitUntilDone:YES];
        }];
    }

下面是加速器的实现

- (void)handleAccelerometer:(CMAccelerometerData *)accelerData
{
    CMAcceleration acceleration = accelerData.acceleration;
    
    float x = -acceleration.x;
    float y = acceleration.y;
    float angle = atan2(y, x);
    
    if(angle >= -2.25 && angle <= -0.75) {
        DLOG(@"竖屏");
    } else if(angle >= -0.75 && angle <= 0.75){
        DLOG(@"左旋屏");
    } else if(angle >= 0.75 && angle <= 2.25) {
        DLOG(@"倒置");
    } else if(angle <= -2.25 || angle >= 2.25) {
        DLOG(@"右旋屏");
    }
    
}
上一篇下一篇

猜你喜欢

热点阅读