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 具有在这种情况下没有意义的其他状态:UIDeviceOrientationUnknownUIDeviceOrientationFaceUpUIDeviceOrientationFaceDown【参考方案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)

iOS 如何获取屏幕大小

AirPlay 镜像的欠扫描问题

为啥applicationFrame高度为460时窗口高度为480?

“UIScreen”没有成员“main”