【问题标题】:iPad/iOS7: 'Page' modal view controller strange behaviour after presenting 'Full screen' view controller from itiPad/iOS7:从它呈现“全屏”视图控制器后“页面”模式视图控制器的奇怪行为
【发布时间】:2014-02-04 11:24:53
【问题描述】:

我的 iPad 应用程序以“页面”呈现样式打开模态视图控制器。如您所知,“页面”展示样式不覆盖展示视图控制器的状态栏以指示页面展示。

应用程序从模态视图控制器打开UIImagePickerController 以制作照片。 UIImagePickerController 具有“全屏”演示风格。关闭图像选择器后呈现模态视图控制器变得高 20px 并与初始视图控制器的状态栏重叠。

我试图用简单的UINavigationController 替换UIImagePickerController,它也破坏了我的模态视图控制器。

有截图:

他们恢复“页面”视图控制器大小的唯一方法是在返回“页面”视图控制器后更改viewController.view.superview.superview.superview.superview 框架的高度。但这真的很奇怪。

在解除嵌套的模态视图控制器后,是否有另一种方法来修复“页面”模态视图控制器的呈现?

更新: 我用这样奇怪的代码来解决我的问题:

#define STATUS_BAR_HEIGHT 20
#define IPAD_PORTRAIT_HEIGHT 1004
#define IPAD_LANDSCAPE_HEIGHT 748
UIView *superview = nil;

// In case of this view controller included in navigationController we have to use superview of navigation's controller view
if (self.navigationController)
    superview = self.navigationController.view.superview;
else
    superview = self.view.superview;

CGRect r = superview.frame;

// Sometimes we have to fix height + origin, sometimes only height (becase view has bottom magnifying)
// In landscape orientation we have to fix 'width' instead of 'height', because that view controller always works in 'portrait' mode
if (self.interfaceOrientation == UIInterfaceOrientationPortrait && r.size.height > IPAD_PORTRAIT_HEIGHT) {
    r.origin.y = STATUS_BAR_HEIGHT;
    r.size.height = IPAD_PORTRAIT_HEIGHT;
}
else if (self.interfaceOrientation == UIInterfaceOrientationMaskPortraitUpsideDown && r.size.height > IPAD_PORTRAIT_HEIGHT) {
    r.size.height = IPAD_PORTRAIT_HEIGHT;
}
else if (self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft && r.size.width > IPAD_LANDSCAPE_HEIGHT) {
    r.size.width = IPAD_LANDSCAPE_HEIGHT;
    r.origin.x = STATUS_BAR_HEIGHT;
}
else if (self.interfaceOrientation == UIInterfaceOrientationLandscapeRight && r.size.width > IPAD_LANDSCAPE_HEIGHT) {
    r.size.width = IPAD_LANDSCAPE_HEIGHT;
}

superview.frame = r;

我不相信没有更优雅的解决方案。任何想法如何改进它?

UPDATE2:我刚刚打开了一个错误。你可以在那里关注它:rdar://15949644

UPDATE3:这是我的示例项目:link

【问题讨论】:

  • 这是一个已知的 Apple 错误。在 iOS7.1 中尚未修复。确保打开错误报告。
  • @LeoNatan,你在其他地方见过这个问题吗?在打开错误报告之前,我想收集更多详细信息。
  • 是的,在我们自己的应用程序中。我们有一个模态页面表单视图控制器,它以全屏显示相机视图控制器,并且在关闭后我们会遇到相同的视觉异常。我们认为这是小问题,所以我们只打开了一个错误报告,并没有寻找解决方法。我可以在周末看一看,看看是否能想出一个更优雅的解决方法,也许在布局系统的某个地方,但我不能做出任何承诺。
  • @LeoNatan,无论如何感谢您的信息。我会在打开错误报告后更新我的问题。
  • 这很容易重现,您的解决方法很好。

标签: ios ipad ios7


【解决方案1】:

没有好的解决方案,这是 Apple 的错误,在修复之前,您必须解决它。它尚未在 iOS 7.1 中修复。我为此制定了一个解决方案,并意识到我也在实施相同的解决方案。这很丑陋,但它有效。

关于这个设计的一句话。我猜为什么苹果会忽略这个问题,因为苹果不会做全屏视图控制器。这当然不是借口,有时除了呈现全屏之外别无选择(例如,我们必须打开相机视图,必须全屏打开)。也许您可以更改您的设计以适应 Apple 的错误。

【讨论】:

  • 其实我也遇到过这个问题,因为我要呈现UIImagePickerController,所以我没有其他选择。谢谢
  • :-) 我们认为这个问题的优先级很低,基本上会留给 Apple 来解决他们的问题。
【解决方案2】:

“确保呈现模态视图的 ViewController 位于 NavigationController 中,这种奇怪现象应该停止。”我最初的回答 - 错误

更新 这听起来确实像一个错误,尽管从用户体验的角度来看,您不应该真正遇到错误。呈现一个“页面”呈现样式的视图控制器,然后以全屏模式呈现另一个视图控制器似乎有点错误。

IMO 从一开始就是糟糕的设计,所以它没有按照您的预期运行的事实可能是因为设置它的人没有预料到有人会这样使用它。

我会,就像我最初的回答虽然简短,但将您的模态呈现视图控制器嵌入导航控制器并将 UIImagPickerViewController 推入其中或将其动画视图添加到您的视图中,就好像它看起来像另一个一样呈现页面样式的模态视图。如果那是你想要的效果。

这些听起来都不完美,一个更完美的解决方案是查看您的应用程序的流程,也许重新评估事物的呈现方式。

【讨论】:

  • 即使使用 NavigationController 也存在问题
  • 有一个示例项目。您可以下载并尝试使用它。
【解决方案3】:

我认为这是 iOS7 的问题,其中 View 的布局略有改变。 我在流行模式自定义视图中遇到了类似的问题,我注意到了相同的行为。 我通过在viewDidLoad

中添加这一行来解决
self.edgesForExtendedLayout = UIRectEdgeNone;

也许它对你的问题的一些提示很有用。

【讨论】:

  • 对我不起作用 :( 你用这条线修改了哪个视图控制器?
  • 已尝试将其放在页面控制器中,或者更确切地说是您将调用模态控制器的位置。
【解决方案4】:

UIImagePicker(或者更广泛地说,UINavigationController)肯定存在不遵守应用程序中任何状态栏设置的问题。

已通过在 UINavigationController 委托中重新应用状态栏设置来讨论和解决此问题(请参阅 UIImagePickerController breaks status bar appearance)。

在您的情况下,您可能需要调用 self.edgesForExtendedLayout = UIRectEdgeNone;或者尝试在委托回调中重置一些状态栏属性

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated;

【讨论】:

  • 这是不正确的。第二张图片是模态页面应该如何打开。
  • @LeoNatan 这是一个全屏模式页面。在 iOS 7 中,所有视图都应该放在状态栏后面。见developer.apple.com/library/ios/documentation/UserExperience/…
  • 你读过这个问题吗?仅在关闭全屏模式视图控制器后才会出现此问题。页面布局不正确。
  • @LeoNatan 抱歉,我确实误读了这个问题,我会编辑我的答案
  • @JackWu,所有以“页面”模式显示的模式视图控制器都存在此问题。我能够在没有 UIImagePickerController 或 UINavigationController 的情况下重现它
【解决方案5】:

看起来这是一个 iOS 错误,现在可以通过这种解决方法解决(它是“页面”模式视图控制器的一种方法)

#define STATUS_BAR_HEIGHT 20
#define IPAD_PORTRAIT_HEIGHT 1004
#define IPAD_LANDSCAPE_HEIGHT 748

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear: animated];

    // In case of iOS7 we need this weird code, because after displaying full screen view controller from 'Page' modal view controller our 'Page' controller
    // incorrectly shifts 20px up
    //
    // I haven't found best solution for now
    // There is my question on SO: http://stackoverflow.com/questions/21146801/ipad-ios7-page-modal-view-controller-strange-behaviour-after-presenting-full
    if (!isIOS6()) {
        [self setNeedsStatusBarAppearanceUpdate];

        UIView *superview = nil;

        // In case of this view controller included in navigationController we have to use superview of navigation's controller view
        if (self.navigationController)
            superview = self.navigationController.view.superview;
        else
            superview = self.view.superview;

        CGRect r = superview.frame;

        // Sometimes we have to fix height + origin, sometimes only height (becase view has bottom magnifying)
        // In landscape orientation we have to fix 'width' instead of 'height', because that view controller always works in 'portrait' mode
        if (self.interfaceOrientation == UIInterfaceOrientationPortrait && r.size.height > IPAD_PORTRAIT_HEIGHT) {
            r.origin.y = STATUS_BAR_HEIGHT;
            r.size.height = IPAD_PORTRAIT_HEIGHT;
        }
        else if (self.interfaceOrientation == UIInterfaceOrientationMaskPortraitUpsideDown && r.size.height > IPAD_PORTRAIT_HEIGHT) {
            r.size.height = IPAD_PORTRAIT_HEIGHT;
        }
        else if (self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft && r.size.width > IPAD_LANDSCAPE_HEIGHT) {
            r.size.width = IPAD_LANDSCAPE_HEIGHT;
            r.origin.x = STATUS_BAR_HEIGHT;
        }
        else if (self.interfaceOrientation == UIInterfaceOrientationLandscapeRight && r.size.width > IPAD_LANDSCAPE_HEIGHT) {
            r.size.width = IPAD_LANDSCAPE_HEIGHT;
        }

        superview.frame = r;
    }
}

【讨论】:

  • 投反对票的人,有什么建议可以改善这个答案吗?我还没有找到其他可行的解决方案。
猜你喜欢
  • 2016-06-08
  • 2019-02-12
  • 2011-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多