【问题标题】:Restricting an application to a specific orientation on IOS 5将应用程序限制在 IOS 5 上的特定方向
【发布时间】:2013-07-05 19:30:54
【问题描述】:

我有一个使用 Cocos2dx 引擎开发的 IOS 应用程序。

应用程序被锁定为特定方向(例如纵向) 除了最近的应用程序栏和根据设备方向的通知外,应用程序中的所有内容似乎都可以正常工作并且方向正确。

我希望能够限制它,使其与应用程序本身具有相同的方向。

我注意到删除 info.plist 文件中的横向方向可以完成这项工作,但我希望能够通过代码来完成。

在 IOS 6 中,我发现我所要做的就是在我的 RootViewController 中覆盖 referredInterfaceOrientationForPresentation 并给出正确的方向,这样就可以了, 但此方法不适用于 IOS 5 及以下版本。

我需要做什么才能在 IOS 5 及更低版本的设备上进行这项工作?

这是RootViewController的代码(不是我写的,我只是添加了最后一个方法,我正在尝试解决通知和最近应用问题)

#include "cocos2d.h"

#import "RootViewController.h"
#import "AppDelegate.h"

#import "misc/deviceOrientation.h"
#import "services/ios/ConfigurationServiceImpl.h"

@implementation RootViewController
@synthesize progressView;
/*
 // The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
    // Custom initialization
    }
    return self;
 }
 */

/*
 // Implement loadView to create a view hierarchy programmatically, without using a nib.
 - (void)loadView {
 }
 */

/*
 // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
 - (void)viewDidLoad {
    [super viewDidLoad];
 }
 */

-(NSUInteger)supportedInterfaceOrientations{

    ConfigurationServiceImpl* configurationService = [ConfigurationServiceImpl instance];
    if ([configurationService isLandscape])
        return UIInterfaceOrientationMaskLandscape;
    else
        return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}

-(BOOL)shouldAutorotate{
    return YES;
}


// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

//    printf("shouldAutorotateToInterfaceOrientation\n");

    //
    // There are 2 ways to support auto-rotation:
    //  - The OpenGL / cocos2d way
    //     - Faster, but doesn't rotate the UIKit objects
    //  - The ViewController way
    //    - A bit slower, but the UiKit objects are placed in the right place
    //

#if GAME_AUTOROTATION==kGameAutorotationNone
    //
    // EAGLView won't be autorotated.
    // Since this method should return YES in at least 1 orientation,
    // we return YES only in the Portrait orientation
    //
    return ( interfaceOrientation == UIInterfaceOrientationPortrait );
#elif GAME_AUTOROTATION==kGameAutorotationCCDirector
    //
    // EAGLView will be rotated by cocos2d
    //
    // Sample: Autorotate only in landscape mode
    //
    if( interfaceOrientation == UIInterfaceOrientationLandscapeLeft ) {
        [[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeRight];
    } else if( interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
        [[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeLeft];
    }
}

    // Since this method should return YES in at least 1 orientation,
    // we return YES only in the Portrait orientation
    return ( interfaceOrientation == UIInterfaceOrientationPortrait );

#elif GAME_AUTOROTATION == kGameAutorotationUIViewController
    //
    // EAGLView will be rotated by the UIViewController
    //
    // Sample: Autorotate only in landscpe mode
    //
    // return YES for the supported orientations
    ConfigurationServiceImpl* configurationService = [ConfigurationServiceImpl instance];
    return [configurationService shouldAutorotateToInterfaceOrientation: interfaceOrientation];

#else
#error Unknown value in GAME_AUTOROTATION

#endif // GAME_AUTOROTATION


    // Shold not happen
    return NO;
}


 //This callback only will be called when GAME_AUTOROTATION == kGameAutorotationUIViewController

#if GAME_AUTOROTATION == kGameAutorotationUIViewController
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft)
        CDeviceOrientation::setDeviceOrientation(CDeviceOrientation::left);
    else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
        CDeviceOrientation::setDeviceOrientation(CDeviceOrientation::right);
    else if (toInterfaceOrientation == UIInterfaceOrientationPortrait)
        CDeviceOrientation::setDeviceOrientation(CDeviceOrientation::down);
    else if (toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
        CDeviceOrientation::setDeviceOrientation(CDeviceOrientation::up);
}
#endif // GAME_AUTOROTATION == kGameAutorotationUIViewController


- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void)dealloc {
    [super dealloc];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    ConfigurationServiceImpl* configurationService = [ConfigurationServiceImpl instance];
    if ([configurationService isLandscape])
        return UIInterfaceOrientationLandscapeRight;
    else
        return UIInterfaceOrientationPortrait;
}


@end

【问题讨论】:

  • 1.如果状态栏和最近应用程序栏的方向不同,那么 iOS 真的不知道您要锁定方向,并且 2. 有 are numerous questions 在这个主题上,请详细说明为什么你的情况不同?
  • 我尝试了我发现的其他帖子中写的所有内容,但似乎没有任何效果
  • 好的,所以您的应用程序 Info.plist 中只列出了一个方向,您在 每个 视图控制器中实现了 shouldAutorotateToInterfaceOrientationshouldAutoRotatesupportedInterfaceOrientations?在完成所有这些操作之后它是否正常工作,这些信息(你尝试过的所有内容)都需要在 OP 中。帮助我们帮助您,我们掌握的信息越多,我们就能越好/更快地为您提供帮助。
  • 我只有一个视图控制器,因为我在我的应用程序(游戏)中使用 Cocos2dx。我的 info.plist 有 4 个方向,2 个用于纵向,2 个用于横向,当我删除 2 个横向时它解决了我的问题,但我正在寻找一种通过代码覆盖 info.plist 值的解决方案,所以我没有触摸 info.plist(我有我的理由),谢谢

标签: ios objective-c ipad ios5 orientation


【解决方案1】:

对于 iOS 5 使用 shouldAutorotateToInterfaceOrientation,对于 iOS 6 使用 shouldAutorotate。在 iOS5 方法中,使用 if case 作为您支持的方向并为它们返回 YES。在您的应用摘要中,启用所有方向。希望这些对您有所帮助。

【讨论】:

  • 我为 IOS 6 尝试了 shouldAutoRotate 并且它没有工作,它当前返回 YES,更改为 NO 对最近的应用程序栏没有影响。成功的方法是实现preferredInterfaceOrientationForPresentation 以返回UIInterfaceOrientationPortrait。但这不适用于 ios 5
  • 尝试添加supportedInterfaceOrientations方法并返回你的方向。
【解决方案2】:

我制作这个代码框架来处理想要和不需要的设备方向,在我的例子中,我想忽略 UIDeviceOrientationUnknown、UIDeviceOrientationFaceUp 和 UIDeviceOrientationFaceDown,缓存最后允许的方向。此代码处理 iPhone 和 iPad 设备,可能对您有用。

- (void)modXibFromRotation {

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
NSString *device = [[UIDevice currentDevice]localizedModel];
UIInterfaceOrientation cachedOrientation = [self interfaceOrientation];

if ([device isEqualToString:@"iPad"]) {

    if (orientation == UIDeviceOrientationUnknown || 
        orientation == UIDeviceOrientationFaceUp || 
        orientation == UIDeviceOrientationFaceDown) {

            orientation = (UIDeviceOrientation)cachedOrientation;
    }

    if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight) {

        /* Your code */
    }

    if (orientation == UIDeviceOrientationPortrait || orientation == UIDeviceOrientationPortraitUpsideDown) {

        /* Your code */     
    }
}

if ([device isEqualToString:@"iPhone"] || [device isEqualToString:@"iPod"]) {

    if (orientation == UIDeviceOrientationUnknown || 
    orientation == UIDeviceOrientationFaceUp || 
    orientation == UIDeviceOrientationFaceDown) {

        orientation = (UIDeviceOrientation)cachedOrientation;
    }

    if (orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight) {

         /* Your code */
    }

    if (orientation == UIDeviceOrientationPortrait || orientation == UIDeviceOrientationPortraitUpsideDown) {

        /* Your code */
    }
  }
}

您必须从视图控制器中的两个位置调用此方法:

首先在您的 App 委托中生成设备方向通知:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.

//**** ADD THIS CODE *****
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

// Add the main view controller's view to the window and display.
self.window.rootViewController = self.mainViewController;
[self.window makeKeyAndVisible];

return YES;

}

然后在您的视图控制器中监听设备方向通知:

- (void)viewDidLoad {   

     [notificationCent addObserver:self
                          selector:@selector(modXibFromRotation)
                              name:UIDeviceOrientationDidChangeNotification object:nil];
}

最后从以下位置调用modXibFromRotation方法:

- (void)viewWillAppear:(BOOL)animated {

    [super viewWillAppear];

    [self modXibFromRotation];
}

这将在视图显示之前调用检查方向方法。

【讨论】:

  • - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { if (toInterfaceOrientation == UIInterfaceOrientationPortrait || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) { return YES; } 否则 { 返回否; } } 上面的代码将让您在 iOS 5 中以纵向和倒置纵向模式定向。根据我提供的代码编写您自己的方法可能会对您有所帮助。
  • 我试过你的代码(没有加载我的配置,只是为了测试它是否限制为纵向)它没有做任何事情。当我运行游戏并且设备面向横向时,游戏应该以纵向打开,但是当我双击主页按钮时,最近的应用程序仍然以横向打开
  • 你必须从以下位置调用这个方法: - (void)viewWillAppear:(BOOL)animated {} 你也可以监听来自 UIDeviceOrientationDidChangeNotification 的通知来触发它。在我的项目中 100% 有效。
  • 你能举个例子吗?
  • 再次检查我的答案,我为我的方法的实现添加了更多代码
猜你喜欢
  • 1970-01-01
  • 2014-03-12
  • 1970-01-01
  • 1970-01-01
  • 2014-05-01
  • 1970-01-01
  • 2012-10-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多