UIScreen applicationFrame 在横向应用程序启动时返回不正确的矩形 (iPhone/iPad)
Posted
技术标签:
【中文标题】UIScreen applicationFrame 在横向应用程序启动时返回不正确的矩形 (iPhone/iPad)【英文标题】:UIScreen applicationFrame returning incorrect rectangle on landscape application launch (iPhone/iPad) 【发布时间】:2010-04-19 02:58:05 【问题描述】:在横向模式下启动我的 iPad 应用程序时无法获得正确的边界。我在 Info.plist 文件中设置了正确的键,并且我的视图控制器在横向(和纵向,自然)中正确启动。
在我的 applicationDidFinishLaunching:
方法中,我在 3 秒延迟后调用选择器,该方法调用 [[UIScreen mainScreen] applicationFrame]
,但它返回给我一个纵向框架(即高度 > 宽度)。
有谁知道如何解决这个问题?对我来说,它闻起来像一个错误(如果是这样,我会提交雷达),但如果它是预期的行为,它记录在哪里?
【问题讨论】:
从现在开始我可以只说“不正确的角度”吗? 【参考方案1】:我从不依赖[[UIScreen mainScreen] applicationFrame]
,尤其是在应用启动期间。
在代码中创建视图时,使用超级视图来设置框架。
如果您使用带有“模拟界面元素”的 xib,它们的大小会正确,一切都会很好。
基于 UINavigationController 的应用
对于基于 UINavigationController 的应用程序,直接从self.navigationController.view
抓取框架,不要尝试使用[self loadView]
和self.view.superview
。 UINavigationController 使用“隐藏的”子视图来完成它的工作——所以直接的超级视图将不起作用。
UINavigationController 很特别,因为在应用启动期间,导航控制器会在调用 loadView
后调整您的视图大小。当自动调整大小开始时,您最终会在屏幕底部有一个小边距。
为什么不用 UIScreen
[[UIScreen mainScreen] applicationFrame]
不能可靠地工作(尤其是在横向启动应用时)。我的经验是视图控制器的interfaceOrientation
属性与applicationFrame
方向不匹配。
【讨论】:
这太重要了!谢谢 这很有帮助!如果我早点找到它,我会节省很多时间!谢谢!【参考方案2】:CGRect bounds = [[UIScreen mainScreen] bounds]; // portrait bounds
if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]))
bounds.size = CGSizeMake(bounds.size.height, bounds.size.width);
【讨论】:
【参考方案3】:当您以横向方式拿着 iPad 并启动应用程序时,视图控制器最初会看到纵向视图的边界(即使方向报告横向)。然后,视图控制器将收到一条消息,在它出现之前旋转到横向。
【讨论】:
那么消息发送到视图控制器旋转后,坐标系是否会反映新的方向?比如消息发送后,width > height?【参考方案4】:当视图控制器处于横向时,这是我获得正确 CGRect 的方式:
CGRect landscapeBounds;
if (self.view.frame.size.width < self.view.frame.size.height)
landscapeBounds = CGRectMake(self.view.frame.origin.y, self.view.frame.origin.x, self.view.frame.size.height, self.view.frame.size.width);
else
landscapeBounds = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
【讨论】:
【参考方案5】:这是设计的。您应该查询您的 superview 的大小并根据需要进行调整。
【讨论】:
你能解释一下为什么这样设计(或至少推测)。如果屏幕已经旋转,我觉得给屏幕提供不正确的边界似乎是不合逻辑的。有问题的superview
是我的应用程序的窗口(我也尝试使用它的框架来获得相同的结果)。
原因是窗口可以独立于屏幕旋转。示例:当纵向应用程序启动 YouTube 视频时,主窗口保持纵向,但横向窗口在其上方显示动画。在动画期间,设备应该被视为纵向还是横向? (加速度计方向与窗口方向分开与状态栏方向分开)
我也注意到了这一点,真的很奇怪。感谢您的提醒。
在这种情况下,我的应用程序窗口是我的超级视图,即使它是横向的,它也会报告纵向边界。令人沮丧。但如果需要,我只需要使用[UIDevice orientation]
来交换 w+h。
-[UIDevice orientation]
不应用于此目的; -[UIApplication statusBarOrientation]
应改为使用。 UIDeviceOrientation
具有在这种情况下没有意义的其他状态:UIDeviceOrientationUnknown
、UIDeviceOrientationFaceUp
和 UIDeviceOrientationFaceDown
。【参考方案6】:
[[UIScreen mainScreen] applicationFrame]
将始终返回纵向矩形,即使应用程序处于横向模式。这与 UIWindow
从不 实际旋转,而只是更改 rootViewController.view
的变换这一事实有关。
为确保您可以在纵向和横向模式下打印根视图对象,您将看到如下内容:
肖像:
<UIView: 0x96290e0; frame = (0 20; 768 1004); ...
风景:
<UIView: 0x96290e0; frame = (0 20; 768 1004); transform = [0, 1, -1, 0, 0, 0]; ...
【讨论】:
【参考方案7】:因此,根据 Apple 的指南,添加一个启动图像并为其赋予后缀 -568h。
我不明白为什么有头脑的人会让系统设置依赖于图形;但我刚刚测试过,它确实有效。
Here is the spot that taught me after a quick search我没有在上面看到这个答案,认为它对某人有用。
S
【讨论】:
【参考方案8】:在 Cordova 插件中使用 dismissViewControllerAnimated 关闭视图时,我遇到了同样的问题。 我修改了 MainViewController 中 viewWillAppear 方法的 SingingAtom 代码,在关闭模式视图后调整了大小:
- (void)viewWillAppear:(BOOL)animated
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
UIDeviceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (UIDeviceOrientationLandscapeLeft == orientation ||
UIDeviceOrientationLandscapeRight == orientation)
if (appFrame.size.width < appFrame.size.height)
appFrame = CGRectMake(appFrame.origin.y, appFrame.origin.x, appFrame.size.height, appFrame.size.width);
self.view.frame = appFrame;
[super viewWillAppear:animated];
【讨论】:
以上是关于UIScreen applicationFrame 在横向应用程序启动时返回不正确的矩形 (iPhone/iPad)的主要内容,如果未能解决你的问题,请参考以下文章
iOS6和iOS7的UIScreen bounds和applicationFrame区别
UIScreen applicationFrame 在横向应用程序启动时返回不正确的矩形 (iPhone/iPad)