在 iPad 上运行的 iPhone 应用程序中横向视图顶部的 20 像素间隙

Posted

技术标签:

【中文标题】在 iPad 上运行的 iPhone 应用程序中横向视图顶部的 20 像素间隙【英文标题】:20px gap on top of landscape view in iPhone app running on iPad 【发布时间】:2010-10-02 23:49:17 【问题描述】:

我正在 iPad 模拟器中运行“仅限 iPhone”的应用程序...当设备的方向更改为横向模式时,我有一个视图控制器启动并以编程方式加载 WebView。这在 iPhone 中运行良好(横向视图顶部没有间隙),但在 iPad 中模拟时,视图顶部有 20 像素(我认为?)间隙。

这是我加载 WebView 的横向视图控制器 viewDidLoad 中的代码:

    [super viewDidLoad];

// Initialize webview and add as a subview to LandscapeController's view
CGRect webFrame = [[UIScreen mainScreen] bounds]; // Use bounds to take up entire screen
self.myWebView = [[[UIWebView alloc] initWithFrame:webFrame] autorelease];
self.myWebView.scalesPageToFit = YES;
self.myWebView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
self.myWebView.delegate = self;
[self.view addSubview: self.myWebView]; 

// remove status bar from top of screen
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];

将状态栏设置为默认,没有影响。

我似乎无法弄清楚为什么这在 iPhone 上会很好,但在 iPad 上却出现??? 有任何想法吗?提前致谢!

【问题讨论】:

【参考方案1】:

屏幕边界在屏幕坐标中。您将 webview 添加为 self.view 的子视图;它的框架位于 self.view 坐标中。您想填充视图,而不是屏幕(UIViewController/UIKit 的其余部分会自动调整视图的大小,最终应该将 Web 视图的大小调整为自动调整大小):

self.myWebView = [[[UIWebView alloc] initWithFrame:self.view.bounds] autorelease];

在 -viewDidLoad 中更改状态栏是不安全的。视图加载可以发生在任何地方(当任何东西调用 viewController.view 时都会发生)。我也不确定您为什么要设置样式;你想设置隐藏性:

在-viewWillAppear:中,做[application setStatusBarHidden:YES animated:animated]; 在-viewWillDisappear:,做[application setStatusBarHidden:NO animated:animated];

最后,您可能会看到不同的行为,因为 iPad 运行的是 OS 3.2.x,而手机运行的是 3.1.x 或 4.x。此外,iPhone 兼容模式使用虚拟状态栏; “真正的”状态栏总是停留在屏幕的边缘。

【讨论】:

感谢 tc!您对 setStatusBarHidden 的评论让我指出了正确的方向! 顺便说一句,以这种方式正确删除状态栏会导致 iPhone 和 iPad 横向视图都包含视图顶部的白色间隙。虽然这并没有解决核心问题,但它表明不调用 setStatusBarHidden 不是问题。【参考方案2】:

顶部的 20 像素几乎总是与状态栏的高度相关。

您发布的代码看起来不错...用于设置UIWebView。但是您将其作为子视图添加到您的视图控制器的view。那个尺寸如何?它的frame 是什么?

【讨论】:

帧大小是:width=320px,height=460px...我猜这会在高度上留下 20px 的差距...【参考方案3】:

我终于想通了。我在原始帖子中没有提到的关键缺失组件是管理景观的视图控制器实际上是作为模态视图实现的。 (有关如何执行此操作的代码,请参阅 View Controller 用户指南)在概念上,我有一个 Portrait 视图控制器。 (这是主控制器)在纵向视图控制器的 viewDidLoad 中,我申请了一个通知程序,该通知程序由方向变化触发,如下所示:

- (void)viewDidLoad 
[super viewDidLoad];

// SECTION to setup automatic alternate landscape view on rotation
// Uses a delegate to bring the landscape view controller up as a modal view controller

isShowingLandscapeView = NO;
// Create Landscape Controller programmatically
self.landscapeViewController = [[LandscapeViewController alloc] initWithNibName:@"LandscapeViewController" bundle:[NSBundle mainBundle]];

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(orientationChanged:)
                                             name:UIDeviceOrientationDidChangeNotification
                                           object:nil];

// END SECTION landscape modal view controller

然后,当方向改变时,这个方法被调用:

- (void)orientationChanged:(NSNotification *)notification

UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;

if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView)

    // Load Landscape view
    landscapeViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    [self presentModalViewController:self.landscapeViewController animated:YES];

    isShowingLandscapeView = YES;

同时我正在从景观视图控制器的 viewWillAppear 方法中移除状态栏:

- (void)viewWillAppear:(BOOL)animated

// remove status bar from top of screen
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:animated];

self.myWebView.delegate = self; // setup the delegate as the web view is shown

这就是引入问题的地方。纵向视图控制器捕获屏幕尺寸,然后作为模态视图转换为横向。然后,viewWillAppear 在 Landscape 视图控制器中移除状态栏。

所以,解决办法是移动

[[UIApplication sharedApplication] setStatusBarHidden:YES animated:animated];

在转换到横向模式视图之前,在纵向视图控制器中声明orientationChanged 方法。

- (void)orientationChanged:(NSNotification *)notification

UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;

if (UIDeviceOrientationIsLandscape(deviceOrientation) && !isShowingLandscapeView)

    // remove status bar from top of screen
    // NOTE: this must be declared BEFORE presenting the Modal View!!!! If it's not, the landscape view will
    //       contain an ugly white bar in place of the missing status bar at the top of the view.
    [[UIApplication sharedApplication] setStatusBarHidden:YES];

    // Load Landscape view
    landscapeViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    [self presentModalViewController:self.landscapeViewController animated:YES];

    isShowingLandscapeView = YES;

请注意,正如上面提到的 tc,如果您希望在返回纵向时显示状态栏,那么您需要

[[UIApplication sharedApplication] setStatusBarHidden:NO animated:animated];

在景观视图控制器的 viewWillDisappear 方法中。

【讨论】:

以上是关于在 iPad 上运行的 iPhone 应用程序中横向视图顶部的 20 像素间隙的主要内容,如果未能解决你的问题,请参考以下文章

iOS 应用程序可在 iPhone 上运行,但不能在 iPad 上运行

iphone应用程序在ipad上运行的问题

检查 Phonegap 应用程序是不是在 iPad 或 iPhone 上运行

应用程序在 iPad 上运行,而其仅限 iPhone

隐藏在 iPad 上运行的 iPhone 应用程序的状态栏

为啥 XCode 说我的 iPhone 应用程序只能在 iPad 上运行?