检测屏幕旋转(通知和传感器方式)
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;
}
}
}
在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(@"右旋屏");
}
}