iPhone(/iPad)上的高度和宽度

8

这只是一个测试应用程序,只有一个AppDelegate类来创建所有内容。我所做的就是创建一个基于窗口的应用程序,在info.plist中将支持的方向设置为仅横向,然后添加以下代码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
[application setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft];

// Override point for customization after application launch.
UIAlertView *test = [[UIAlertView alloc] initWithTitle:@"hu" message:@"hui" delegate:nil cancelButtonTitle:@"hi" otherButtonTitles:nil];
[test show];
[window makeKeyAndVisible];
    NSLog(@"win %f - %f", window.bounds.size.width, window.bounds.size.height);
return YES;
}

如果没有第一行设置状态栏方向,警告视图会出现在纵向模式中,即使界面的其余部分是横向左侧。

无论如何,日志仍然会显示:

win 768.000000 - 1024.000000

这是错误的方法(因此当我在我的真实应用程序中添加子视图时,框架不正确)。

苹果似乎在界面旋转方面出了很多问题,因为我一直遇到各种问题,在iPhone上我没有记得发生过这种情况,所以请有人告诉我如何解决这个问题。

我将提供500声望(这几乎是我的全部声望),给能够至少解释为什么会发生这种情况并希望提供解决方案的人。


你使用的是哪个SDK版本? - ImHuntingWabbits
为什么你要在AppDelegate里这样做?为了避免这个问题,我在AppDelegate里创建了一个BOOL值,默认为False,直到调用了该方法,它才会变为TRUE。然后在我的MainVC中的viewWillLoad中启动一个计时器,检查AppDelegate BOOL是否为TRUE。如果是,则触发显示警告的方法。为了让它看起来更好看些,在我的MainVC上也显示默认图像,直到消息出现。这可能看起来有点不正规,但我并不总是需要显示警报视图,所以我也检查了那一点。 - ingh.am
7个回答

17

我认为iOS 应用程序编程指南中的"在横屏模式下启动"大部分解释了您的测试应用程序中发生的情况:

在iOS中,应用程序通常以纵向模式启动,以匹配主屏幕的方向。如果您有一个既可以纵向又可以横向运行的应用程序,则应始终最初以纵向模式启动,然后让其视图控制器根据设备的方向旋转界面。但是,如果您的应用程序仅以横向模式运行,则必须执行以下步骤使其最初以横向方向启动:
- 在应用程序的Info.plist文件中,添加UIInterfaceOrientation键,并将其值设置为横向模式。对于横向方向,您可以将此键的值设置为UIInterfaceOrientationLandscapeLeft或UIInterfaceOrientationLandscapeRight。 - 在横向模式下布置您的视图,并确保它们的自动调整选项已正确设置。 - 覆盖您的视图控制器的shouldAutorotateToInterfaceOrientation:方法,并仅返回所需的横向方向为YES,纵向方向为NO。 重要提示:前面的步骤假定您的应用程序使用视图控制器来管理其视图层次结构。视图控制器提供了大量基础设施,用于处理方向更改以及其他复杂的与视图相关的事件。如果您的应用程序未使用视图控制器(如游戏和其他基于OpenGL ES的应用程序),则需要负责旋转绘图表面(或调整绘图命令),以便以横向模式呈现内容。
关于你的测试应用,关键部分是最后一部分。你没有视图控制器,因此需要完全负责以你想要的方向设置UI。这就是为什么你必须手动设置状态栏方向的原因。
我认为第一段话的意思是iOS应用程序总是以纵向模式启动,然后根视图控制器立即且无任何动画地旋转其视图以匹配设备方向,一旦它添加到窗口中。这意味着UIWindow本身不会旋转,因此其尺寸始终是以纵向方向为基准(正如tadej5553所说)。此外,所有UIWindow子视图的框架也将以纵向方向为基准(因为框架始终是在父视图的坐标系中定义的)。因此,无论如何旋转设备,根视图控制器的框架始终是以纵向方向为基准。但是,由于视图的边界属性是以其自己的坐标系定义的,因此高度和宽度应反映当前视图的方向。
不清楚你在真实应用中想要实现什么,但推荐的做法是为纵向方向布置视图,然后设置它们的自动调整属性以处理自动旋转(无论是在应用程序启动后立即发生还是稍后发生)。

非常好的答案,我会接受它并在我能够时开始另一个悬赏(虽然不是500:\),并授予给你,但是个人而言,我更喜欢Deniz的答案,所以他得到了悬赏。您很好地解释了为什么通常会发生这种情况,这对我非常有用,如果我现在可以分配奖金,我会这样做。 - Jonathan.
iPad是一个例外,因为它的主屏幕可以旋转到横向模式。 - bentford

10

UIWindow并不知道旋转方向。旋转方法都封装在UIViewController中(例如自动旋转等)。

UIAlertView使用UIApplication的statusBarOrientation属性来选择提示框的方向。

// Rotate to a specific orientation.  This only rotates the status bar and updates the statusBarOrientation property.
// This does not change automatically if the device changes orientation.
@property(nonatomic) UIInterfaceOrientation statusBarOrientation;

从 SDK headers 可以看出,statusBarOrientation 不会自动改变。因此,你或者 UIViewController(自动旋转)都应该更改这个属性。

如果你一开始是竖屏状态(与 UIWindow 的默认方向一致),并且使用 shouldAutorotateToInterfaceOrientation 并让 UIViewController 处理旋转,它会在每次设备方向更改时更改 UIApplication 的 statusBarOrientation

但是如果你一开始是横屏模式,你需要手动设置 statusBarOrientation 一次。

希望这可以帮到你。


1
感谢你用UIAlertView来解释并告诉我该做什么。 - Jonathan.
在找到这个解决方案之前,我花了很长时间来尝试解决这个问题。将[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];放在我的loadView的第一行就解决了问题。谢谢! - Andy
我觉得我刚刚浪费了2个小时,试图让我的iPad应用程序(iOS5)仅在横向模式下启动。这个方法有效了,非常感谢。 - Jasper

6
使用视图的边界

4

窗口大小始终是竖屏方向的大小。一直都是。

但视图将给出正确的测量值(关于方向),因此请确保使用它们。


我刚刚做了这个,它正确地改变了状态栏的差异(20像素),但仍然没有切换宽度和高度。 - Jonathan.
在横向模式下,宽度仍然为768(屏幕高度为1024),在纵向模式下则相反。 - Jonathan.
使用边界而不是视图框架来获取正确的坐标。 - tadejsv

3
这是我做的使其工作的步骤:
在Info.plist中,确保有以下参数: - Initial interface orientation = Landscape (right home button) - Supported interface orientations - Item 0 = Landscape (right home button) - Item 1 = Landscape (left home button)
添加一个基于xib的视图控制器,并在其中添加一个自动调整大小的视图(消除调整大小问题等)。 请注意,我在这里使用了带有视图控制器的导航控制器,因为它是我手边有的,但我认为这也适用于单个VC。
在您的应用程序委托中添加一些代码:
_rootViewController = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:nil]; 
_navigationController = [[UINavigationController alloc] initWithRootViewController:self.launcherViewController];
[window addSubview:self.navigationController.view]; //I think this is the key.
[window makeKeyAndVisible];

我认为关键在于视图,如果没有视图,我尝试了一下,在iPhone上它可以正常工作,但在iPad上,就像你所说的那样,警报只会在纵向模式下显示。当我重新添加视图后,警报以所需的横向模式显示。


3

不要手动操作状态栏,尝试在info.plist文件中将UISupportedInterfaceOrientations设置为UIInterfaceOrientationLandscapeLeft。然后,一旦启动应用程序,它就应该全部设置好了。

手动设置状态栏方向有点“低级”。您的视图控制器还需要在shouldAutorotateToInterfaceOrientation实例方法中返回UIInterfaceOrientationLandscapeLeft


你为什么没有任何 UIView?据我所知,你应该始终在窗口内拥有一个容器 UIView。你不是直接将控件视图放在窗口里了吧? - Nimrod
在我的真实应用程序中(我在这个问题中谈论的那个只是尝试让它工作),我有一个子类化的UIViewController,当我使用window.frame作为视图的框架在App Delegate中添加它的视图时,它会添加具有纵向模式尺寸的视图(因此视图的底部被切掉了,右侧有一个间隙)。 - Jonathan.
它就是无法正确设置窗口框架大小,当界面旋转时应该交换宽度和高度,但由于窗口框架大小不正确,这意味着子视图的框架大小也是错误的,因此其子视图的子视图也是错误的。 - Jonathan.
你在UIViewController中实现了shouldAutorotateToInterfaceOrientation吗? - Nimrod
当我提出这个问题时,我没有一个视图控制器,但现在Tadej的答案让我放置了一个,并且实现shouldAutorotate...仍然没有改变任何东西。 - Jonathan.
显示剩余2条评论

0

我一直在为将我的应用程序硬编码为仅横向模式而遇到问题。大部分时间没有视觉问题,但底部20像素的按钮无法被选中。我在主UIWindow上执行了clipToBounds操作,并在其图层上添加了边框,发现UIWindow位于状态栏下方。我尝试将UIWindow的x偏移量更改为20(UIWindow仍处于纵向状态,其内容为横向),但这意味着我的UIControllers向下移动了20个像素(不确定原因)。虽然这是与您的问题不同的问题,但我也发现了与您相同的问题,即打印时出现的边界和框架似乎是正确的。

总之,长话短说,我将我的plist从UIInterfaceOrientationLandscapeLeft更改为UIInterfaceOrientationLandscapeRight,并且还更改了我的UIViewController方法:

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

所有的问题都解决了。很多次我发誓苹果的旋转代码中有错误,结果证明是我实现某些功能的方式有问题,但我认为这个问题肯定是苹果的问题。

如果这个方法解决了你的问题,请告诉我。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接