如何正确设计多方位的iPad应用程序

时间:2012-07-23 23:00:30

标签: iphone objective-c ipad interface-builder orientation

现在设计多方位iPad应用程序的正确方法是什么?我已经阅读了很多Apple文档,网络资源和一些SO Q& A.以下是我的初始要求:

  • 这必须适用于iOS 5及更高版本。无需创建与previos版本iOS的兼容性。
  • 我希望尽可能在不同的NIB文件中定义纵向和横向UI。
  • 我的NIB文件将针对不同方向的相同UI元素具有不同的图像(例如,我将使用header.pngheader-landscape.png UIImageView。
  • 应用程序将有多个屏幕,我需要能够在每个屏幕上切换方向。

那我该怎么办?

  • 每个屏幕创建一个VC并替换willRotate处理程序中的基础视图?
  • 每个方向创建一个VC?但那么你如何正确切换它们呢?
  • 简单地重新安排元素将无效(我认为),因为我必须重新加载图片。
  • 用代码写一切(我真的很讨厌这个想法)?

截至今天,这个问题的正确方法是什么?

5 个答案:

答案 0 :(得分:17)

我实际上认为这是一个非常复杂的主题,就像大多数架构问题一样。我不相信你应该尝试用一种技术解决问题。

为了不排除此页面上的所有其他答案,I posted a full-writeup on my bloga link to some sample code, too

摘要

应该首选在.xib文件中表达您的UI,尽管您允许自己偏离此范围的程度部分取决于将修改您的应用程序的人员的技能组合未来。它可能不只是程序员

首选项

强烈建议使用一个.xib文件和一个UIViewController子类实现一个逻辑视图。努力做到这一点真的很难。在您的XIB的根autoresizesSubviews=YES上设置view,并正确调整子视图' autoresizingMask随着屏幕尺寸/方向的变化而弯曲可能会有很长的路要走。

但是,这总是不够。如果您的布局需要横向调整,超出自动调整可以处理的范围,我使用两个主要选项。您应该选择哪一个取决于您观看的内容。

选项一

如果纵向与横向的布局没有太大差异,那么我建议您使用一个.xib,并在View Controller中使用一些代码来调整旋转布局。

选项二

如果横向与纵向差异非常重要,那么我建议为每个方向使用一个.xib(使用严格的命名约定,如MyViewController.xibMyViewController-landscape.xib)。但是,两个.xib文件都应将文件的所有者连接到相同的View Controller 类!对我而言,这是关键。

如果你要做除了首选替代方案以外的任何事情,我建议创建一个可重用的UIViewController基类来自动执行此操作,并使其保持一致。它的工作量比你最初想象的要多,而且在每个需要轮换处理的UIViewController子类中继续这样做是很愚蠢的。


解决方案

我创建了这样一个基类,put it in a sample project here.你可以看到一个Hello World示例,说明我应该如何处理所有三个场景:

  • 一个视图控制器和一个.xib,仅限自动调整(我的FirstViewController
  • 一个视图控制器和两个.xibs,它们之间自动切换(我的SecondViewController
  • 一个视图控制器和一个.xib,在旋转时具有次要的编程布局(ThirdViewController

我使用的RotatingViewController基类同样适用于iPhone应用程序。我实际上有一个更复杂的版本来处理维护iPad iPhone,纵向横向布局(适用于通用应用)。

但是,这个问题只是关于iPad,所以我将其剥离,以便更容易理解。

My base class还有一个实用程序imageNamed:方法,可帮助加载适合当前方向的图像(使用 image-landscape.png 约定命名)。但是,我认为stretchable UIImages should be used绝大多数时候都是on the blog post I reference

我没有这样做,但RotatingViewController也可以尝试遍历其subviews树并更新image或{{1}上的UIButton属性当设备方向改变时,对象。我没有那么长,但你可以。

这些建议的更多基本原理可用{{3}}

答案 1 :(得分:4)

所以,由于缺乏对这个问题和时间的答案是一个问题,我最终做了以下事情:

  • 使用Interface Builder以纵向方式为所有屏幕创建NIB文件。将所有需要布局的控件绑定到出口。
  • 使用IB创建横向方向的NIB文件,但仅用于参考以查看UI元素的框架在横向中的位置。
  • 添加了代码,以便在willAutoRotate处理程序中将所有元素重新排列为横向和返回纵向。

这种方法让我可以灵活地创建IB中大多数UI的列表。我仍然需要保留代码以将元素重新排列到不同的方向,但通常这只涉及setFrame方法用于标签,按钮等,而imageNamed用于图像。这是一个小得多的范围,然后直接在代码中创建所有UI。

一旦SO允许,我将在这个问题上打开一个赏金,因为我认为这个问题对于为iPad / iPhone创建通用和多向应用程序的开发人员来说非常重要和有用。

答案 2 :(得分:2)

我使用了3种不同的技术,其中1种我认为是处理多种方向的“正确”方法。

  1. 不正确:创建了两个不同的nib / xib。不是“坏”,但是当你在UIViewController中不断重建UIView时,处理上下文和状态会很痛苦。
  2. 不正确:使用一个笔尖并根据绝对坐标重新定位它们。这是错误的做法。我一遍又一遍地看到这一点,但这是你完成处理多种观看模式的最糟糕的方式。这种情况的一个症状是UIViews是设备方向感知。完全不必要。
  3. 正确:对视图内的元素使用 autoresizingMask 将它们浮动到设备旋转的正确位置,调整使用CGRect无法实现的功能帧。我只需要做一次这样的事情。恕我直言,这是处理多个设备方向的“正确”方式。 UIView和任何子视图不需要知道旋转。您可以在每个屏幕上使用一个包含许多子视图的VC并保持简单。如果您的布局可以通过这种方式设计,使用浮动元素,那么您就是金色的,用户界面也是轻而易举的。
  4. 只是我的两分钱。

    编辑:iOS 6引入了AutoLayout,可用于代替“struts和spring” - https://developer.apple.com/library/ios/documentation/userexperience/conceptual/AutolayoutPG/Introduction/Introduction.html

答案 3 :(得分:0)

令我失望的是,Apple没有为给定的视图控制器提供使用多个XIB文件(每个方向一个)的方法 - 这是处理方向问题的一种很好的方法,因为自动调整很少很好地处理方向(它只适用于非常简单的界面)。

您可以这样做:为肖像创建XIB,并为XIB中的每个子视图分配唯一的标记属性。然后复制XIB,并重新进行横向布局(现在你有两个XIB,一个肖像和一个横向)。

当您的应用启动时,您最初会从适合启动方向的XIB创建视图控制器。迭代遍历所有子视图,并创建一个包含所有子视图帧的字典,由每个子视图的标记属性键入。

接下来,从另一个方向的XIB创建一个临时视图控制器,并进行相同的递归迭代,将所有按标记键入的帧存储到第二个字典(每个字典匹配其中一个方向,并应相应地命名)。然后处置第二个临时视图控制器。

layoutSubviews中(实际上在viewDidLayoutSubviews中,由于您正在处理视图控制器并且您可以执行iOS 5+),因此您需要做的就是递归遍历所有子视图,并且根据子视图的标签属性,从适合当前方向的帧字典中为每个子视图分配帧。

此技术将允许您保留视图控制器的状态,而无需在每次方向更改时重新加载它。它还允许您使用IB布局视图控制器,因此您不必编写一堆手动布局代码。

答案 4 :(得分:-3)

为什么要在可以完成所有工作的应用程序之后运行?当您设计一个应用程序时,您可以决定它的最佳方向 - 横向或纵向 - 即使您的应用程序的设计需要反向(所有都在横向,1-2个控制器是纵向或副反之亦然,你会相应地制作笔尖。那么,在某些情况下,你需要一个控制器来支持所有方向,你会做到这一点。

但是试图让所有控制器支持所有方向......好吧,我发现这个想法有点奇怪。

万一你仍然想要这样做,你已经列出了可能的解决方案,我喜欢最后一个选项。