如何在没有 [UI 设备 setValue:forKey:@"orientation"] 的情况下更改 UI 方向
How to change UI orientation without [UIDevice setValue:forKey:@"orientation"]
我的目标是使用按钮改变 lock/unlock 方向。在锁定模式下,方向可以通过按钮切换,在解锁模式下,方向由传感器确定。
我试图用 [[UIDevice currentDevice] setValue:[NSNumber numberWithInt:orientation] forKey:@"orientation"]
来实现这个,但是这段代码有问题。
假设目前我的应用是 'Lock mode, portrait UI, portrait device'。然后我将设备旋转到左侧横向,并解锁方向。我预计 [[UIDevice currentDevice] orientation]
应该是 UIDeviceOrientationLandscapeLeft
。但是这个值是 UIDeviceOrientationPortrait
虽然真实的设备是横向的!
我也尝试使用下面的代码通知中心。
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(onDeviceOrientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
但是这段代码不能正常工作。如果设备处于横向并且 UI 方向由 [[UIDevice currentDevice] setValue:[NSNumber numberWithInt:UIDeviceOrientationPortrait]
设置为纵向,则当我将设备旋转为纵向时 onDeviceOrientationChanged
不会被调用。我认为设备的方向值已经设置为纵向(通过我的代码,而不是传感器)。
ps。当然,我勾选了 Required full screen 选项。
编辑:知道如何获得不受[[UIDevice currentDevice] setValue]
影响的设备的真实方向也是一个很好的答案。
我使用 MotionManager
解决了这个问题。当我锁定(或更改)方向时,[[UIDevice currentDevice] setValue:[NSNumber numberWithInt:orientation] forKey:@"orientation"]
就足够了。
但是,当我解锁方向时,我使用 MotionManager
和以下代码刷新了方向。
CMMotionManager motionManager = [[CMMotionManager alloc] init];
[motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue]
withHandler:^(CMAccelerometerData * _Nullable accelerometerData, NSError * _Nullable error) {
[motionManager stopAccelerometerUpdates];
CMAcceleration acceleration = accelerometerData.acceleration;
UIInterfaceOrientation orientation;
if (acceleration.x >= 0.75) {
orientation = UIInterfaceOrientationLandscapeLeft;
} else if (acceleration.x <= -0.75) {
orientation = UIInterfaceOrientationLandscapeRight;
} else if (acceleration.y <= -0.75) {
orientation = UIInterfaceOrientationPortrait;
} else if (acceleration.y >= 0.75) {
orientation = UIInterfaceOrientationPortraitUpsideDown;
} else {
return;
}
[[UIDevice currentDevice] setValue:[NSNumber numberWithInt:orientation]
forKey:@"orientation"];
[UINavigationController attemptRotationToDeviceOrientation];
}];
当然,您应该了解 supportedInterfaceOrientations
和 shouldAutorotate
方法。
我的目标是使用按钮改变 lock/unlock 方向。在锁定模式下,方向可以通过按钮切换,在解锁模式下,方向由传感器确定。
我试图用 [[UIDevice currentDevice] setValue:[NSNumber numberWithInt:orientation] forKey:@"orientation"]
来实现这个,但是这段代码有问题。
假设目前我的应用是 'Lock mode, portrait UI, portrait device'。然后我将设备旋转到左侧横向,并解锁方向。我预计 [[UIDevice currentDevice] orientation]
应该是 UIDeviceOrientationLandscapeLeft
。但是这个值是 UIDeviceOrientationPortrait
虽然真实的设备是横向的!
我也尝试使用下面的代码通知中心。
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(onDeviceOrientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
但是这段代码不能正常工作。如果设备处于横向并且 UI 方向由 [[UIDevice currentDevice] setValue:[NSNumber numberWithInt:UIDeviceOrientationPortrait]
设置为纵向,则当我将设备旋转为纵向时 onDeviceOrientationChanged
不会被调用。我认为设备的方向值已经设置为纵向(通过我的代码,而不是传感器)。
ps。当然,我勾选了 Required full screen 选项。
编辑:知道如何获得不受[[UIDevice currentDevice] setValue]
影响的设备的真实方向也是一个很好的答案。
我使用 MotionManager
解决了这个问题。当我锁定(或更改)方向时,[[UIDevice currentDevice] setValue:[NSNumber numberWithInt:orientation] forKey:@"orientation"]
就足够了。
但是,当我解锁方向时,我使用 MotionManager
和以下代码刷新了方向。
CMMotionManager motionManager = [[CMMotionManager alloc] init];
[motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue]
withHandler:^(CMAccelerometerData * _Nullable accelerometerData, NSError * _Nullable error) {
[motionManager stopAccelerometerUpdates];
CMAcceleration acceleration = accelerometerData.acceleration;
UIInterfaceOrientation orientation;
if (acceleration.x >= 0.75) {
orientation = UIInterfaceOrientationLandscapeLeft;
} else if (acceleration.x <= -0.75) {
orientation = UIInterfaceOrientationLandscapeRight;
} else if (acceleration.y <= -0.75) {
orientation = UIInterfaceOrientationPortrait;
} else if (acceleration.y >= 0.75) {
orientation = UIInterfaceOrientationPortraitUpsideDown;
} else {
return;
}
[[UIDevice currentDevice] setValue:[NSNumber numberWithInt:orientation]
forKey:@"orientation"];
[UINavigationController attemptRotationToDeviceOrientation];
}];
当然,您应该了解 supportedInterfaceOrientations
和 shouldAutorotate
方法。