支持iOS 6中一个视图的不同方向

29

我想仅将我的应用程序中的一个视图旋转为左横屏或右横屏。 我的所有其他视图都在竖屏模式下,并且我已将我的应用程序设置为仅支持竖屏模式。由于iOS 6中更改了方向,我不确定如何做到这一点。我尝试了下面发布的方法。有谁能告诉我我做错了什么?谢谢!

-(BOOL)shouldAutorotate {
return YES;
}

-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{

return UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskLandscapeLeft;
} 

我也尝试过:

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(didRotate:)
                                            name:UIDeviceOrientationDidChangeNotification
                                           object:nil];
return YES;//UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskLandscapeLeft;
} 


 -(void)didRotate:(NSNotification *)notification {
 UIDeviceOrientation orientation = [[notification object] orientation];

if (orientation == UIDeviceOrientationLandscapeLeft) {
    [theImage setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
    [self.view setTransform:CGAffineTransformMakeRotation(M_PI / 2.0)];
} else if (orientation == UIDeviceOrientationLandscapeRight) {
    [theImage setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
    [self.view setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
} else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
    [theImage setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
    [self.view setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
} else if (orientation == UIDeviceOrientationPortrait) {
    [theImage setTransform:CGAffineTransformMakeRotation(M_PI / 2.0)];
    [self.view setTransform:CGAffineTransformMakeRotation(M_PI / 2.0)];
}
}

这个视图是否在TabBarController中? - Hackmodford
感谢您的回复@Hackmodford。不是,只是一个导航控制器。 - Alex G
7个回答

19

这对我有用 如何在iOS 6中强制UIViewController为竖屏方向

从UINavigationController创建一个新的分类,覆盖旋转方法:

-(BOOL)shouldAutorotate
{
    return [self.topViewController shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [self.topViewController supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [self.topViewController preferredInterfaceOrientationForPresentation];
}

@end 

1
我看到有两种解决方案建议使用类别(category)来覆盖已有的方法 - 这肯定是一个非常糟糕的想法,因为现在你整个应用程序中所有的导航控制器都会有这些方向方法设置! - fatuhoku

6
iOS 6 在处理视图旋转方面有所改变。仅支持应用程序 Info.plist 中定义的方向,即使您返回其他方向也不行。请尝试在项目中选择所有方向作为支持。
处理视图旋转
在iOS 6中,您的应用程序支持在应用程序的Info.plist文件中定义的界面方向。视图控制器可以覆盖supportedInterfaceOrientations方法以限制支持的方向列表。通常,系统仅在窗口的根视图控制器或全屏显示的视图控制器上调用此方法;子视图控制器使用其父视图控制器提供的窗口部分,并且不再直接参与有关支持哪些旋转的决策。应用程序方向掩码和视图控制器方向掩码的交集用于确定可以将视图控制器旋转到哪些方向。
您可以为打算以特定方向全屏呈现的视图控制器覆盖preferredInterfaceOrientationForPresentation。
在iOS 5及更早版本中,UIViewController类仅以纵向模式显示视图。要支持其他方向,必须覆盖shouldAutorotateToInterfaceOrientation:方法,并为子类支持的任何方向返回YES。如果您的视图的自动调整大小属性已正确配置,则可能是您需要执行的所有操作。但是,UIViewController类提供了其他钩子,供您根据需要实现其他行为。通常,如果您的视图控制器打算用作子视图控制器,则应支持所有界面方向。
当可见视图控制器发生旋转时,将在旋转期间调用willRotateToInterfaceOrientation:duration:、willAnimateRotationToInterfaceOrientation:duration:和didRotateFromInterfaceOrientation:方法。视图被其父级调整大小和定位后,还将调用viewWillLayoutSubviews方法。如果视图控制器在方向更改时不可见,则永远不会调用旋转方法。但是,当视图变为可见时,将调用viewWillLayoutSubviews方法。您对此方法的实现可以调用statusBarOrientation方法以确定设备方向。

(C) 苹果文档: UIViewController


1
那么,在我设置了plist以支持所有方向之后,您能否解释一下需要支持所有纵向视图的具体代码,以及仅需要横向视图的唯一1个视图所需的代码?非常感谢。我会接受的。 - Alex G
我尝试过以下代码,但是在只想要竖屏的视图中仍然会旋转为横屏,这当然是因为我尝试了您启用所有方向的建议:- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return UIInterfaceOrientationMaskPortrait; } - Alex G
@AlexG,你为什么要更改那个属性?它已经说过了:“视图控制器可以重写supportedInterfaceOrientations方法来限制支持的方向列表。”只需要覆盖“supportedInterfaceOrientations”属性就可以了。 - Nekto
1
我尝试过了,但应用程序崩溃并显示“支持的方向没有共同的方向”。如果我启用所有可能的方向,那么它可以工作,但只有当我将手机旋转到横向时才能这样做,当视图加载时它不会自动执行,然后即使我返回UIInterfaceOrientationMaskPortrait,所有其他视图也不会停止旋转到横向。还有其他建议吗?非常感谢,我真的很感激。 - Alex G
@AlexG 看这里:https://dev59.com/KGcs5IYBdhLWcg3w1XbZ - Nekto
显示剩余2条评论

2

按照以下步骤进行操作:

  • 创建 UINavigationController 的子类并重写旋转方法。
  • 在 AppDelegate 中创建一个 BOOL 类型的 islandscape 属性。
  • 当视图被推入/弹出/呈现/解除时,调整此 BOOL 值。

示例项目

我创建了一个示例项目,可以完美运行。请下载并集成到您的项目中:https://www.dropbox.com/s/nl1wicbx52veq41/RotationDmeo.zip?dl=0


那看起来像是 BOOL island escape。一定是真的。 - Jonesopolis

0

我已经搜索了几个小时的解决方案!

所以在实现必要的方法后,shouldAutorotate 不需要设置为 YES,因为它已经默认设置好了:

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
     return UIInterfaceOrientationPortrait;
}

当需要显示方向与其他视图不同的UIViewController时,我创建了一个带有以下实现的UIStoryboardSegue

#import "Showing.h"

@implementation Showing

- (void)perform{
    NSLog(@"Showing");
    UIViewController *sourceVC = self.sourceViewController;
    UIViewController *presentingVC = self.destinationViewController;

    [sourceVC.navigationController presentViewController:presentingVC 
                                                animated:YES 
                                              completion:nil];
}

@end

UIStoryboard 中,我使用这个 segue(显示)连接了视图:

enter image description here

这很重要,你正在使用

presentViewController:animated:completion:

而不是

pushViewController:animated:

否则方向将无法再次确定。
我一直在尝试类似的事情。
[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];

或者这个方法应该放在UIViewController中,当设备方向改变时调用。我也尝试在我的自定义UIStoryboardSegues中在presentingViewControllerdismissViewController之前调用它:

[UIViewController attemptRotationToDeviceOrientation];

或者

NSNumber *numPortrait = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:numPortrait forKey:@"orientation"];

但它们中没有一个起作用。当然,最后一个示例不应该是一个选项,因为如果苹果更改其api的任何内容,这可能会在您的应用程序内部引起问题。

我还尝试使用AppDelegate方法,并始终在查找实际visibleViewController的正确UIInterfaceOrientation之后,在此方法内确定方向,但是在从一个方向切换到另一个方向时有时会发生崩溃。所以我仍然想知道为什么它变得如此复杂,似乎也没有任何文档能够正确解释它。即使遵循this part didn't help也没有帮助。


0

UIViewController+OrientationPermissions.h

@interface UIViewController (OrientationPermissions)
   + (void)setSupportedOrientations:(UIInterfaceOrientationMask)supportedOrientations;
   + (UIInterfaceOrientationMask)supportedOrientations;
@end

UIViewController+OrientationPermissions.m

@implementation UIViewController (OrientationPermissions)
static UIInterfaceOrientationMask _supportedOrientations;

+ (void)setSupportedOrientations:    (UIInterfaceOrientationMask)supportedOrientations {
    _supportedOrientations = supportedOrientations;
}

+ (UIInterfaceOrientationMask)supportedOrientations {
    return _supportedOrientations;
}

@end

在你的UIApplication代理中

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
    return [UIViewController supportedOrientations];
}

然后在所需的视图控制器上执行以下操作

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [UIViewController setSupportedOrientations:UIInterfaceOrientationMaskAll];
}

离开此视图控制器前不要忘记重置掩码

请注意,如果您正在使用UINavigationController或UITabBarController,请参阅https://dev59.com/318d5IYBdhLWcg3w3FRk#28220616如何绕过此问题


0

我有一个:

TabbarController -> NavigationController -> ViewController -> ViewController

我继承了 UITabBarController 并添加了...

-(NSUInteger)supportedInterfaceOrientations{
    if (self.selectedIndex >= 0 && self.selectedIndex < 100) {
        for (id vC in [[self.viewControllers objectAtIndex:(unsigned long)self.selectedIndex] viewControllers]) {
            if ([vC isKindOfClass:[CLASS_WHICH_SHOULD_ALLOW class]]) {
                return UIInterfaceOrientationMaskPortrait + UIInterfaceOrientationMaskLandscape;
            }
        }
    }
    
    return UIInterfaceOrientationMaskPortrait;
}


-2

有问题请尝试。我会在两天后解决。

//AppDelegate.m - 很不幸,这个方法在iOS6之前是不可用的。

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;

if(self.window.rootViewController){
    UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
    orientations = [presentedViewController supportedInterfaceOrientations];
}

return orientations;
}

//MyViewController.m - 返回每个UIViewController支持的方向

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

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