如何通过编程方式设置设备(UI)方向?

23

希望屏幕上的所有内容(UI)都能够从左横屏旋转到右横屏或反之亦然。

我应该如何做?这是私密的吗?

我知道

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {}

UIInterfaceOrientationMask可以用来指定UI支持的屏幕方向,但有没有一种方法可以强制只允许一种方向?

谢谢。


shouldAutorotateToInterfaceOrientation 在 iOS 6.0 中已被弃用。请参见此处 - JohnK
强制竖屏代码,对于我的应用程序非常有效。 https://dev59.com/jWcs5IYBdhLWcg3wrmDC#21142932 - ppVen
可能是重复的问题:如何以编程方式确定iPhone界面方向? - Suhaib
10个回答

24

在iOS中,[[UIDevice currentDevice] setDeviceOrientation:UIDeviceOrientationSomeOrientation] 方法不存在。但是我们可以通过旋转带有状态栏的视图来实现:

- (void)showAlbum {
    // check current orientation
    if ([[UIApplication sharedApplication] statusBarOrientation] != UIInterfaceOrientationLandscapeLeft) {
        // no, the orientation is wrong, we must rotate the UI
        self.navigationController.view.userInteractionEnabled = NO;
        [UIView beginAnimations:@"newAlbum" context:NULL];
        [UIView setAnimationDelegate:self];
        // when rotation is done, we can add new views, because UI orientation is OK
        [UIView setAnimationDidStopSelector:@selector(addAlbum)];
        // setup status bar
        [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft  animated:NO];
        // rotate main view, in this sample the view of navigation controller is the root view in main window
        [self.navigationController.view setTransform: CGAffineTransformMakeRotation(M_PI / 2)];
        // set size of view
        [self.navigationController.view setFrame:CGRectMake(0, 0, 748, 1024)];
        [UIView commitAnimations];
    } else {
        [self addAlbum];
    }

}

谢谢!我只需要UIView.transform属性,因为我正在处理的视图只需要处于横向方向。 - aiham
CoreMotion方向感知如何?它是否随状态栏方向而改变? - Hari Honor
不,它不会。CoreMotion发送设备运动事件,这段代码无法更改设备方向,它只更改应用程序屏幕方向。 - UIBuilder
我不知道你如何使用UIDeviceOrientation来设置setStatusBarOrientation。根据class reference所述,您需要使用UIInterfaceOrientation。但也许您可以解释一下您的理由? - JohnK

18

我用这个方法成功了:

 if (self.interfaceOrientation != UIInterfaceOrientationPortrait) {
    // https://dev59.com/KnVC5IYBdhLWcg3wykej
    // http://openradar.appspot.com/radar?id=697
    // [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait]; // Using the following code to get around apple's static analysis...
    [[UIDevice currentDevice] performSelector:NSSelectorFromString(@"setOrientation:") withObject:(id)UIInterfaceOrientationPortrait];
}

首先感谢Chis!但是为什么苹果不让我们使用这个方法(setOrientation:)呢?它非常简单易用。但是这也是苹果的证明吗?谢谢。 - NicTesla
1
使用这种方法会不会增加在苹果审核过程中被拒绝的风险? - Rahul Patel
3
上述代码无法在ARC下编译,因为它没有将NSInteger转换成id。然而,您可以使用NSInvocation代替。但话说回来,在iOS 6下这个方法对我没用。 - Ryan Ballantyne
4
您可以使用以下代码解决ARC问题:[[UIDevice currentDevice] performSelector:NSSelectorFromString(@"setOrientation:") withObject:(__bridge id)((void*)UIInterfaceOrientationPortrait)]; 不过,在iOS6下这种方法无效。 - Hermann Klecker

16

这个方法被称为确定您的界面是否应自动旋转到给定的旋转方向(即让UIKit来完成困难的工作,而不是手动完成)。

因此,如果您希望您的应用程序仅在横向模式下运行,则可以使用以下代码实现该方法:

return UIInterfaceOrientationIsLandscape(interfaceOrientation);

如果您希望您的UI自动旋转到所有方向,则只需使用以下代码:

return YES;

这是您所询问的内容吗?


不是通过代码在程序的不同时间将UI方向设置为不同的方向,以便在某些情况下可以镜像另一个设备。 - Sam Jarman
哦,好的,那么在这种情况下,我可能会在委托方法中为您的VC支持的方向返回YES,然后尝试使用以下代码强制更改方向: [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];我不知道我是否曾经亲自尝试过以这种方式强制更改方向,但它可能有效... - tobyc
不确定这是否是您的问题,但请将您的 shouldAutorotateToInterfaceOrientation 方法更改为:return UIInterfaceOrientationIsLandscape(interfaceOrientation); - tobyc
然后也许可以按照Justin Spahr-Summers的建议模态呈现视图控制器。这样,您可能不必使用setOrientation强制更改方向。进行疯狂的方向更改可能会很麻烦... - tobyc
@half_brick:我按照你说的做了,效果很好。我的 nib 文件是横向模式,特定视图始终处于横屏状态。但是,如果我将硬件逆时针旋转到横屏(另一边),视图控制器就不会旋转……需要帮助吗? - Ahsan
你们在谈论一个特定的 nib,但是设备方向呢?设备方向是否只是与 nib 的方向匹配?我有一个游戏,其中 glView 的渲染方式是横向的,但设备(或其他什么东西?)保留了纵向方向。我很难将你的答案放入这个范围内... - Danny

5
如果您展示了一个实现了-shouldAutorotateToInterfaceOrientation:方法并且只支持一个方向的模态视图控制器,整个界面将会自动强制进入该方向。我认为没有其他编程方式可以改变方向。

3

1
谢谢,我需要这个答案! - sunlover3

3
也可以采用这种简单的方法:
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];

回到之前的页面:

[[UIApplication sharedApplication] setStatusBarHidden:NO];
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];

这帮助我解决了IPAD横向启动问题:根本没有接收到任何触摸事件。调用setStatusBarHidden神奇地解决了这个问题。 - Benjamin Piette

2
这个问题的解决者是:Guntis Treulands https://dev59.com/snA85IYBdhLWcg3wEPVL#10146270
//-----------------------------------
// FORCE PORTRAIT CODE
//-----------------------------------
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:NO];
//present/dismiss viewcontroller in order to activate rotating.
UIViewController *mVC = [[UIViewController alloc] init];
[self presentModalViewController:mVC animated:NO];
[self dismissModalViewControllerAnimated:NO];

0

在相关主题中建议的那样, shouldAutorotateToInterfaceOrientation已被弃用。新的应用程序应该利用以下方法,如苹果公司的UIViewController Class Reference所述,直到它们自己变得过时:

  • shouldAutorotate,
  • preferredInterfaceOrientationForPresentation; 和
  • attemptRotationToDeviceOrientation

据我所知,最好为需要锁定(即具有首选)方向模式与上一个不同的视图使用不同的视图控制器。


0

虽然这不是一个理想的解决方案,但对我来说很有效。

- (void)viewDidLoad
{
   self.view.transform = CGAffineTransformIdentity;
   self.view.transform = CGAffineTransformMakeRotation((M_PI * (90) / 180.0)); 
   self.view.bounds = CGRectMake(0.0, 0.0, 480, 320);
}

0
if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
        objc_msgSend([UIDevice currentDevice], @selector(setOrientation:),    UIInterfaceOrientationLandscapeLeft );
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接