Ios 旋转设备时,是否可以对UIView使用自定义旋转?
我正在为我的应用程序创建一个摄像头viewController,我希望使用与iOS默认摄像头应用程序相同的想法:录制按钮始终位于设备的同一侧。内容只是随着自己的轴旋转,而不是整个屏幕翻转 我已经“成功”创建了这个。我只允许风景。打开时,它看起来像这样:Ios 旋转设备时,是否可以对UIView使用自定义旋转?,ios,objective-c,uiview,rotation,uiinterfaceorientation,Ios,Objective C,Uiview,Rotation,Uiinterfaceorientation,我正在为我的应用程序创建一个摄像头viewController,我希望使用与iOS默认摄像头应用程序相同的想法:录制按钮始终位于设备的同一侧。内容只是随着自己的轴旋转,而不是整个屏幕翻转 我已经“成功”创建了这个。我只允许风景。打开时,它看起来像这样: Figure 1 <- top of device ------------------------------ | ------------------- | || |
Figure 1
<- top of device
------------------------------
| ------------------- |
|| | |
|| | --- |
|| camera-view | | ^ | |
|| | --- |
|| | |
| ------------------- |
-----------------------------
问题是整个视图将旋转,因此屏幕将始终显示图1
,而“设备顶部”将改变方向
通过在-(BOOL)shouldAutorotate
中返回NO
,我得到了我想要的结果,尽管一切都会自然颠倒。
然后,通过注册设备方向参考,并使用我自己的选择器,我可以使用例如[btnRecord setTransform:CGAffineTransformMakeRotation(-M_PI)]以编程方式旋转每个控件(例如按钮、文本等)代码>
旋转时将变换设置为每个控件,同时防止控制器实际旋转,我会得到想要的结果。有点
问题是:
当使用我上面描述的方法时,我直观地得到了正确的结果,但我怀疑我应该用另一种方法来处理这个问题。当我收到来自其他应用程序(如Mail、Facebook等)的通知时,它们将始终以原始方向显示。这是有道理的。如果此viewController在LandscapeLeft中启动,然后转到LandscapeRight,则所有我的控件和整个视图都将动画化,并且看起来非常适合该方向,但传入的通知将在屏幕底部倒置显示。当然,这是我在shouldAutorotate
中返回NO
的结果
在默认的摄像头应用程序中,他们已经解决了这个问题,所以这一定是可能的。
是否有一种方法可以启用自动旋转,同时防止控制器的视图实际旋转?当时我能想到的唯一解决方案是创建一个完全抵消旋转动画的动画,使其处于静止状态,但这听起来很糟糕,我想找到一个更好的方法。您可以通过使用加速计检测应用程序激活的方向:
- (void)applicationWillEnterForeground:(UIApplication*)application {
// [motionManager stopAccelerometerUpdates] doesn't stop
// all gathered accelerometer data, but we want trigger it once.
static BOOL read = NO;
// applicationWillEnterForeground will happen lot of times :-)
read = NO;
CMMotionManager* motionManager = [[CMMotionManager alloc]init];
[motionManager
startAccelerometerUpdatesToQueue:
[[NSOperationQueue alloc] init]
withHandler:
^(CMAccelerometerData* data, NSError* error) {
if (!read) {
read = YES;
[motionManager stopAccelerometerUpdates];
CGFloat accx = data.acceleration.x;
CGFloat accy = data.acceleration.y;
dispatch_async(
dispatch_get_main_queue(),
^{
[[UIApplication sharedApplication]
setStatusBarOrientation:
deviceOrientationFromAcceleration(accx, accy)
animated:NO];
});
}
}];
}
deviceOrientationFromAcceleration()
函数定义为
int deviceOrientationFromAcceleration(CGFloat x, CGFloat y) {
// Get the current device angle
float xx = -x;
float yy = y;
float angle = atan2(yy, xx);
if (angle >= -2.25f && angle <= -0.75f) {
return UIInterfaceOrientationPortrait;
}
else if (angle >= -0.75f && angle <= 0.75f) {
return UIInterfaceOrientationLandscapeRight;
}
else if (angle >= 0.75f && angle <= 2.25f) {
return UIInterfaceOrientationPortraitUpsideDown;
}
else if (angle <= -2.25f || angle >= 2.25f) {
return UIInterfaceOrientationLandscapeLeft;
}
return 0;
}
int deviceOrientationFromAcceleration(CGFloat x,CGFloat y){
//获取当前设备角度
浮动xx=-x;
浮动yy=y;
浮动角度=atan2(yy,xx);
如果(角度>=-2.25f&&angle=-0.75f&&angle=0.75f&&angle),是否隐藏状态栏?
int deviceOrientationFromAcceleration(CGFloat x, CGFloat y) {
// Get the current device angle
float xx = -x;
float yy = y;
float angle = atan2(yy, xx);
if (angle >= -2.25f && angle <= -0.75f) {
return UIInterfaceOrientationPortrait;
}
else if (angle >= -0.75f && angle <= 0.75f) {
return UIInterfaceOrientationLandscapeRight;
}
else if (angle >= 0.75f && angle <= 2.25f) {
return UIInterfaceOrientationPortraitUpsideDown;
}
else if (angle <= -2.25f || angle >= 2.25f) {
return UIInterfaceOrientationLandscapeLeft;
}
return 0;
}