【问题标题】:iPhone Landscape FAQ and SolutionsiPhone Landscape 常见问题解答和解决方案
【发布时间】:2011-02-26 13:21:38
【问题描述】:

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

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

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

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

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

【问题讨论】:

标签: iphone uiviewcontroller orientation landscape


【解决方案1】:

documentation 中的内容:

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

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

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

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

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

文档中没有的内容:

一点背景:

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

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

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

解决办法:

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

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

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

【讨论】:

  • 谢谢!这对我帮助很大。不幸的是,堆栈上的视图控制器在它们存在时发生旋转。如果它们是在发生旋转后添加的,它们的方向不会正确改变。使用动画推送时:YES 您可以手动调用 willRotateToInterfaceOrientation:duration 和 didRotateFromInterfaceOrientation 来解决此问题。但是,使用动画:NO 这什么都不做。我一直在尝试我能想到的一切。有什么建议?解决方案、变通方法?
  • 从 iOS8 开始,此方法(shouldAutorotateToInterfaceOrientation)已被弃用 - 现在您应该尝试:preferredInterfaceOrientationForPresentation - 希望对某人有所帮助!
【解决方案2】:

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

希望它对某人有所帮助!

P.S.在 sdk 3.2.5 ios 5.0.1 上测试。

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

【讨论】:

    【解决方案3】:

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

    UIViewController *viewController = [[UIViewController alloc] init];
    [self presentModalViewController:viewController animated:NO];
    [self dismissModalViewControllerAnimated:NO];
    [viewController release];
    

    【讨论】:

      【解决方案4】:

      我想补充一下 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 相关的选择器在使用 animated:YES 执行时都会发疯。具体来说,视图控制器的动画方向错误。您可以使用 animated:NO 并将此类动画的使用限制在层次结构中更深层次的其他 UINavigationController(即您推送到根导航控制器堆栈的那些)。

      非常感谢任何输入。

      【讨论】:

      • 感谢您的意见。应该注意的是,FAQ 是从 iOS 3.1 或 3.2 开始编写的,从那时起,很多事情可能已经发生了变化。我从来没有遇到过您描述的问题(也没有检查过您的解决方法),但是您提供它作为帮助他人的参考真是太好了!谢谢。
      • @Johannes:感谢您的回复!您是否从未遇到过这个问题,因为您在横向时没有推送新的视图控制器?否则,如果你有,你对我有什么建议吗?如何在正确的方向上这样做? (请参阅我的编辑,了解我为什么要寻找不同的解决方案。)
      • 据我所知,我只推送了两个视图控制器,一个“主控制器”在“方向控制器”中显示我的应用程序的内容,然后按需使用 MFMailComposeViewController呈现为模态对话框(效果很好并且可以正确旋转)。你用的是什么iOS?
      • 查看此答案:stackoverflow.com/a/4035140/835428 使用 UIWindow 视图移除方法可为您提供正确的 navigationController 推送/弹出动画。
      • 另外注意iOS6中修复了view controller动画方向问题
      【解决方案5】:

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

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

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

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

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

      【讨论】:

        【解决方案6】:

        这会起作用...

        UIWindow *window = [[UIApplication sharedApplication] keyWindow];
            UIView *view = [window.subviews objectAtIndex:0];
            [view removeFromSuperview];
            [window addSubview:view];
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-02-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-11
          • 1970-01-01
          • 2020-03-08
          • 2011-12-27
          相关资源
          最近更新 更多