18

关于如何实现对横向/纵向模式自动旋转进行适当处理的 iPhone 应用程序,这里存在很多困惑和一组相应的问题。当需要以横向模式启动时,实现这样的应用程序尤其困难。最常见的观察到的效果是混乱的布局和不再识别触摸的屏幕区域。

简单搜索标记的问题iphonelandscape揭示这些问题,这些问题在某些情况下会发生:

已经提出了一组不同的解决方案,其中一些包括通过 CoreGraphics 完全自定义的动画,而另一些则建立在从主 nib 加载的第一个视图控制器始终显示正确的观察上。

我花了大量时间调查这个问题,最终找到了一个解决方案,它不仅是部分解决方案,而且应该在所有这些情况下都有效。我打算通过这篇 CW 帖子为其他在横向模式下遇到 UIViewControllers 问题的人提供一种常见问题解答。

请提供反馈并通过合并任何相关观察来帮助提高这篇文章的质量。如果您知道,请随时编辑和发布其他/更好的答案。

4

6 回答 6

13

文档中的内容:

在您的视图控制器中,覆盖 shouldAutorotateToInterfaceOrientation: 以声明您支持的界面方向。每次设备方向更改时,控制器基础结构将/应该检查此属性。

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
{
   return  (orientation == UIInterfaceOrientationLandscapeRight);
}

这是您的视图控制器需要做的绝对最小值。如果要以横向模式启动应用程序,则需要将以下键添加到.plist文件中:

<key>UIInterfaceOrientation</key>
<string>UIInterfaceOrientationLandscapeRight</string>

Apple 建议在横向右模式下启动仅横向应用程序(请参阅用户体验指南 > 立即启动下的 HIG )。

文档中没有的内容:

一点背景:

每次您尝试加载不同于从主 nib 加载的视图控制器时,您的视图控制器既不会询问其支持的界面方向,也不会询问其框架设置是否正确。只有绑定到窗口的第一个视图控制器才能正确布局。

其他人建议使用连接到主窗口的“MasterViewController”,其他控制器将其视图作为子视图添加到主窗口,而不是直接连接到窗口中。虽然我发现这个解决方案是一个可行的选择,但在将模态视图控制器添加到这些子视图的情况下它不能正常工作。如果您有一些应该能够自动旋转的子视图(主控制器将阻止),也会出现问题。

使用未记录的 API 来强制特定的界面方向也不是一种选择。

解决方案:

到目前为止,我发现的最佳解决方案是修改“MasterViewController”解决方法。不是使用自定义的“MasterViewController”,而是使用UINavigationController隐藏的导航栏和隐藏的标签栏。如果从该控制器的导航堆栈中推送/弹出所有其他视图,则将正确管理该堆栈上控制器的自动旋转。

presentModalViewController:animated:通过导航堆栈上的任何视图控制器呈现的模态控制器UINavigationController将被旋转并以正确的布局呈现。如果您希望模态视图控制器可旋转到与父视图控制器不同的方向,则需要在显示模态视图时从shouldAutorotateToInterfaceOrientation控制器的方法返回所需的方向。为了在模态控制器关闭时正确恢复界面方向,您需要确保在调用之前返回父控制器所需的方向。您可以在视图控制器上使用私有来管理它(例如)。shouldAutorotateToInterfaceOrientationdismissModalViewController:animated:BOOLBOOL isModalMailControllerActive_

我很快就会添加一段示例代码,现在为时已晚。如果还有任何未解决的问题或这篇文章有任何不清楚的地方,请告诉我。随意编辑和改进。

于 2010-06-01T21:44:27.000 回答
7

我对 ios 应用程序有一个有趣的要求:

主视图控制器应该只有横向,但所有其他(可以从主视图推送)可以是横向和纵向。

出现问题 - 当我推送到一个新的 viewController,然后将其旋转为纵向 - 并且弹回 - 主视图不再是横向的。另外 - 打开应用程序,它不是横向的。

为了保持主视图控制器景观,无论从哪个方向弹出/推送,我都做了以下事情:(在 viewWillAppear 中:)

//set statusbar to the desired rotation position
[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO];

//present/dismiss viewcontroller in order to activate rotating.
UIViewController *mVC = [[[UIViewController alloc] init] autorelease];
[self presentModalViewController:mVC animated:NO];
[self dismissModalViewControllerAnimated:NO];

希望它会帮助别人!

PS在 sdk 3.2.5 ios 5.0.1 上测试。

PS 感谢您提供此常见问题解答中的所有信息!

于 2012-04-13T18:24:38.350 回答
3

对于第二个要点,如果您想使用 pushViewController 从仅纵向视图变为仅横向视图,我发现的一个简单技巧是将以下代码放入推送控制器的 viewDidLoad 中:

UIViewController *viewController = [[UIViewController alloc] init];
[self presentModalViewController:viewController animated:NO];
[self dismissModalViewControllerAnimated:NO];
[viewController release];
于 2011-10-29T07:33:50.647 回答
2

我想添加到 Johannes 的答案(使用 UINavigationController 作为 MasterViewController)。

我发现的缺点是新推送到主 VC 导航堆栈的 ViewController 不会适应任何先前的方向变化。简而言之,已经在堆栈上的 VC 被旋转,从它们呈现的模态视图控制器也被旋转,但新添加的 VC没有被旋转。

在找到一个可行的方法之前,我已经尝试了很多技巧来解决这个问题。大多数仅适用于 pushViewController:动画设置为 YES。

为了彻底解决这个问题,我将子类化UINagivationController和覆盖pushViewController:animated:如下:

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    // Correctly autoOrient the given view controller
    [self presentModalViewController:viewController animated:NO];
    [self dismissModalViewControllerAnimated:NO];

    // Push it as normal (now in its correct orientation)
    [super pushViewController:viewController animated:animated];
}

临时(并且非常不可见地)呈现视图控制器允许它接收其方向更新。然后可以以正确的方向将其推入导航堆栈。

请让我知道这是否适合您。非常欢迎所有更新和改进!

最后,我强烈推荐 Johannes 的轮换管理方法。

编辑:从堆栈中弹出视图控制器的更新

似乎所有与 popViewController 相关的选择器在使用动画执行时都会发疯:YES。具体来说,视图控制器的动画方向错误。您可以使用 animated:NO 并将此类动画的使用限制在层次结构中更深层次的其他 UINavigationController(即,您推送到根导航控制器堆栈上的那些)。

非常感谢任何输入。

于 2011-03-16T15:09:52.460 回答
2

我正在开发一个 iPad 应用程序,它在启动时显示一系列项目的垂直滚动画廊视图。在横向模式下,共有 4 个项目。在肖像中有三个。转动 iPad 方向时,它应该刷新图库以使项目整齐地放在屏幕上。然后我双击一个项目以深入查看该项目的模式视图。然后我用那个项目做一些事情。最后我关闭了模态视图。

在刷新或方向更改期间,图库视图根据屏幕宽度(或高度)和来自 UIViewController.interfaceOrientation 的当前方向计算要显示的项目数。

我在让它正常工作时遇到问题。有时,在我关闭模式对话框后,它只会横向显示两个项目。

起初我使用 UIViewController.view.frame.size 值来计算画廊项目的数量。当模态视图被关闭时,此帧大小不正确,例如宽度和高度已反转,即使在显示模态对话框时方向没有改变。

我切换到使用应用程序委托([[UIApplication sharedApplication] delegate]] 并使用 window.frame.size 来计算要显示的画廊项目的数量。window.frame.size 在方向更改和模式对话框下保持正确。画廊项目现在正确显示。

于 2012-12-12T04:46:20.227 回答
-3

这将工作...

UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    UIView *view = [window.subviews objectAtIndex:0];
    [view removeFromSuperview];
    [window addSubview:view];
于 2012-10-22T11:40:23.087 回答