13

我有一个导航控制器,它有几个视图控制器。我需要支持所有视图控制器的所有方向,除了一个只支持横向的特殊视图控制器。这个特殊的视图控制器出现在导航堆栈的中间。我做了很多研究,但找不到任何好的解决方案。以下是我已阅读并尝试过的链接。

http://www.iphonedevsdk.com/forum/iphone-sdk-development/3219-force-landscape-mode-one-view.html#post60435

如何将屏幕旋转为横向?

如何从纵向模式自动旋转到横向模式? iPhone - 仅在一个视图控制器上允许横向方向 http://goodliffe.blogspot.com/2009/12/iphone-forcing-uiview-to-reorientate.html

接下来我将尝试替换导航控制器presentModalViewController以显示特殊的视图控制器。然后我将在特殊的视图控制器内部创建一个新的导航视图控制器来推送后续的视图控制器。

如果有人有更好的想法,请告诉我。非常感谢!

更新:我已经成功使用了我上面描述的方法:替换pushViewControllerpresentModalViewController创建一个新的导航控制器。

4

5 回答 5

9

推送到导航控制器堆栈的每个视图控制器都必须支持相同的方向。这意味着不可能有一些视图控制器只支持纵向,而另一些只支持横向。换句话说,同一个导航控制器堆栈上的所有视图控制器都应该在委托中返回相同的结果:

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

但是有一个简单的解决方案!这是一个从纵向到横向的示例。这是执行此操作的步骤,下面是支持它的代码。

  1. 创建一个“假”视图控制器,它将作为子导航控制器的根。这个视图控制器应该支持横向。
  2. 创建 a 的新实例UINavigationController,将“假”视图控制器的实例添加为 root,并将横向视图控制器的实例添加为第二个视图控制器
  3. UINavigationController从父视图控制器将实例呈现为模态

首先,使用以下代码创建一个新的视图控制器(FakeRootViewController):

@interface FakeRootViewController : UIViewController
@property (strong, nonatomic) UINavigationController* parentNavigationController;
@end

@implementation FaceRootViewController
@synthesize parentNavigationController;
// viewWillAppear is called when we touch the back button on the navigation bar
(void)viewWillAppear:(BOOL)animated {
  // Remove our self from modal view though the parent view controller
  [parentNavigationController dismissModalViewControllerAnimated:YES];
}
(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
   return (interfaceOrientation == UIInterfaceOrientationIsLandscape(interfaceOrientation));
} 

这是呈现您希望在横向模式下显示的视图控制器的代码:

FakeRootViewController* fakeRootViewController = [[FakeRootViewController alloc] init];[fakeRootViewController.navigationItem setBackBarButtonItem:backButton]; // Set back button
// The parent navigation controller is the one containing the view controllers in portrait mode.
fakeRootViewController.parentNavigationController = parentNavigationController;

UINavigationController* subNavigationController = // Initialize this the same way you have initialized your parent navigation controller.

UIViewController* landscapeViewController = // Initialize the landscape view controller

[subNavigationController setViewControllers:
   [NSArray arrayWithObjects:fakeRootViewController, 
                                               landscapeViewController, nil] animated:NO];

[_navigationController presentModalViewController:subNavigationController animated:YES];

请记住,landscapeViewController 也应该有这个实现:

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
   return (interfaceOrientation == UIInterfaceOrientationIsLandscape(interfaceOrientation));
} 
于 2012-06-09T06:11:41.027 回答
1

有一个私有 API 可以强制改变方向。放入您的推送视图控制器-viewWillAppear:

if ([UIDevice instancesRespondToSelector:@selector(setOrientation:)]) {
    [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];
}

要禁止编译器警告,请将其添加到视图控制器的 .m 文件中:

@interface UIDevice()
- (void)setOrientation:(UIDeviceOrientation)orientation; // private API to let POIEntryVC be pushed over landscape route view
@end

与往常一样,在使用私有 API 时,存在被拒绝的风险以及在未来的操作系统版本中被破坏的风险。风险自负!

通常,在大多数情况下,呈现模态视图控制器是更好的解决方案。

于 2012-12-10T12:45:10.763 回答
0

它应该像实现一样简单

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

在每次UIViewController推入你的UINavigationController. 在一个UIViewController人的视图不应该旋转的情况下,return NO对于那个特定的特定方向UIViewController。不过这里有个问题,如果你的UINavigationController工具

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

它将阻止其 viewControllers 接收该方法。在这种情况下,您应该使用将消息转发到 topViewController

[[self topViewController] shouldAutorotateToInterfaceOrientation:interfaceOrientation];
于 2011-02-17T02:25:31.353 回答
0

您可以尝试在您的代码中UINavigationController调用当前可见视图的shouldAutorotateToInterfaceOrientation. 在我的情况下,我有UINavigationController一个UITabBarController但你可以将它调整到其他情况。

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    if ([appDelegate.tabBarController.selectedViewController respondsToSelector:@selector(topViewController)])
    {
        UINavigationController *nc = (UINavigationController*)appDelegate.tabBarController.selectedViewController;
        return [nc.topViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
    }
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
于 2011-04-14T23:11:53.557 回答
0

您可以采取行动:根据 schellsan 的建议更改您的代码,下一步 - 尝试将 currentViewController(它将推送到导航 viewController)作为属性添加到 appDelegate。当您尝试推送视图控制器时,请在此之前将其设置为当前视图控制器。接下来 - 在导航控制器中创建 rootViewController 的子类。在这个子类中的 owload 方法

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Overriden to allow any orientation.
    return [appDelegate.currentViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}

如果您不使用导航栏并在弹出旧控制器后推送新控制器,它应该可以工作

于 2011-09-23T06:55:13.137 回答