UINavigationController 中仅支持一个视图的横向

发布于 2024-10-17 22:03:00 字数 1277 浏览 1 评论 0原文

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

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 替换导航控制器,以显示特殊的视图控制器。然后我将在特殊视图控制器内创建一个新的导航视图控制器以推送后续视图控制器。

如果有人有更好的主意,请告诉我。真的很感激!

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

I have a navigation controller which have a few view controllers. I need to support all orientations for all view controllers except one special view controller which only supports landscape. This special view controller appears in the middle of the navigation stack. I have done quite a lot of research but couldn't find any good solution. Here are the links that I have read and tried.

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

How to rotate screen to landscape?

How to autorotate from portrait to landscape mode?
iPhone - allow landscape orientation on just one viewcontroller
http://goodliffe.blogspot.com/2009/12/iphone-forcing-uiview-to-reorientate.html

Next I am going to try to replace navigation controller with presentModalViewController in order to display the special view controller. Then I am going to create a new navigation view controller inside the special view controller to push the subsequent view controllers.

If anyone has a better idea, please let me know. Really appreciated!

UPDATE: I have successfully use the method I described above: replace pushViewController with presentModalViewController and create a new navigation controller.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

叹倦 2024-10-24 22:03:00

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

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

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

  1. 创建一个“假”视图控制器,该控制器将成为子导航控制器的根。该视图控制器应该支持横向。
  2. 创建 UINavigationController 的新实例,添加“假”视图控制器的实例作为根,添加横向视图控制器的实例作为第二个视图控制器
  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));
} 

Every view controller pushed onto the navigation controllers stack have to support the same orientations. This means that it is not possible to have some view controllers only supporting portrait and others only supporting landscape. In other words all view controllers on the same navigation controller stack should return the same in the delegate:

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

But there is a simple solution to this! Here is an example for going from portrait to landscape. Here is the steps to do it and below is code to support it.

  1. Create a ‘fake’ view controller that will be root in a sub navigation controller. This view controller should support landscape.
  2. Create a new instance of a UINavigationController, add an instance of the ‘fake’ view controller as root and an instance of your landscape view controller as second view controller
  3. Present the UINavigationController instance as modal from the parent view controller

First, create a new view controller (FakeRootViewController) with this code:

@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));
} 

Here is the code to present the view controller that you wish to show in landscape mode:

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];

Remember that the landscapeViewController should also have this implementation:

(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
   return (interfaceOrientation == UIInterfaceOrientationIsLandscape(interfaceOrientation));
} 
怎会甘心 2024-10-24 22:03:00

有一个私有 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 时的未来操作系统版本。风险自负!

一般来说,在大多数情况下,提供模态视图控制器是更好的解决方案。

There's a private API to force an orientation change. Put in your pushed view controller's -viewWillAppear::

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

To suppress the compiler warning, add this to the .m file of your view controller:

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

As always, there's a risk of being rejected and a risk of breaking in future OS versions when using private APIs. Do at your own risk!

Generally, presenting a modal view controller is the better solution in most cases.

小忆控 2024-10-24 22:03:00

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

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

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

You can make actions:
Change Your code with accordance of schellsan suggestion, next -
Try to add currentViewController(which will push to navigation viewController) as property to appDelegate. When You attempt to push view controller, set it to current view controller before this. Next - make a subclass of rootViewController in navigation controller. In this subclass owerload method

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

It should works if You not using a navigation bar and pushes new controller after popping an old

浅笑轻吟梦一曲 2024-10-24 22:03:00

它应该像在

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

推送到 UINavigationController 中的每个 UIViewController 中实现一样简单。如果某个 UIViewController 的视图不应旋转,则针对该特定 UIViewController 中的特定方向返回 NO
不过,这里有一个问题,如果您的 UINavigationController 实现了,

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

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

[[self topViewController] shouldAutorotateToInterfaceOrientation:interfaceOrientation];

It should be as simple as implementing

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

in each UIViewController pushed into your UINavigationController. In the case that one UIViewController's view shouldn't rotate, return NO for that specific orientation in that specific UIViewController.
There's a gotcha here though, if your UINavigationController implements

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

it will block its viewControllers from receiving that method. In that case, you should forward the message to the topViewController using

[[self topViewController] shouldAutorotateToInterfaceOrientation:interfaceOrientation];
慕巷 2024-10-24 22:03:00

您可以在 UINavigationController 中尝试此代码来调用当前可见视图的 shouldAutorotateToInterfaceOrientation。就我而言,我在 UITabBarController 中有 UINavigationController,但您可能可以将其适应其他情况。

- (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);
}

You could try this code in your UINavigationController to call the current visible view's shouldAutorotateToInterfaceOrientation. In my case I have the UINavigationController in a UITabBarController but you could probably adapt it to other cases.

- (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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文