使用 overCurrentContext 呈现视图控制器,然后推送到导航堆栈会导致导航栏重叠

Posted

技术标签:

【中文标题】使用 overCurrentContext 呈现视图控制器,然后推送到导航堆栈会导致导航栏重叠【英文标题】:Presenting view controller with overCurrentContext then pushing to navigation stack results in navigation bar underlapping 【发布时间】:2017-02-23 02:25:09 【问题描述】:

由于导航栏问题,我的头撞到了墙上。请参阅此sample project,以更好地了解我要实现的目标。基本上,我的应用结构是这样的:

NavController -root-> ViewControllerA -> button -> push -> ViewControllerB                            --> ViewControllerC
                                                              |                                      |
                                                            button -> presentModally                 |
                                                              |                                      |
                                                              V                                      |
                                                        PopoverViewController                        |
                                                              |                                      |
                                                            button -> push to the nav controller     |
                                                              |                                      |
                                                              |                                      |
                                                              ---------------------------------------

导航堆栈的第二个视图控制器(称为 B)上的按钮将呈现一个具有清晰背景的模态视图控制器(其模态呈现样式为 overCurrentContext,看起来像一个弹出框):

然后,弹出框上的一个按钮会将一个新的视图控制器推送到导航堆栈(称为 C):

[

弹出框由 B 呈现,而不是实际的导航控制器(B 定义呈现上下文)。这样当弹出框将 C 压入堆栈时,C 不仅会覆盖 B,还会覆盖弹出框。

当关闭 C 时会出现问题。导航堆栈弹回 B,而弹出框仍在顶部(这是我的意图)。但是,B 现在填充了导航视图控制器的整个框架(在 C 被推动之前,B 的顶部被固定到导航栏)。这会导致 B 顶部附近的视图被导航栏剪裁:

查看 UI Inspector 确认这是因为 B 的视图现在填充了导航控制器的视图:

在 C 出现之前情况并非如此。关于导致这种情况发生的任何想法?

【问题讨论】:

偶然解决? 【参考方案1】:

您正在手动将视图控制器推送到没有导航控制器的堆栈上。更好的方法是使用 segue 标识符从视图控制器 B 到视图控制器 C。在情节提要中设置 segue 后,您将看到视图控制器 C 自动获得一个导航栏。您可能希望使用从弹出视图控制器到 B 的委托方法来触发 segue。

【讨论】:

我试过了。从 B 到 C 做了一个show segue,并使用弹出框的 tap 函数到 B 的委托方法来触发 segue。它的行为仍然相同。我还尝试将 B 的 definesPresentationContext 设置为 false。这解决了 C 被剪裁的问题,但它也导致弹出框由导航控制器呈现,在所有进一步的 VC 被推入堆栈的顶部。我尝试为弹出框修改不同的modalPresentationStyles,但overCurrentContext 似乎是唯一满足我要求的。【参考方案2】:

我遇到了一个与这个非常相似的问题。我正在使用.overCurrentContext 演示模式演示视图控制器。当 viewController 显示时,导航就在它上面!

为了解决我刚刚要求导航显示新视图控制器而不是旧视图控制器的问题。

viewController.navigationController?.present(navigationController, animated: true, completion: nil)

通过这种方式,viewController 将不再位于导航的后面。我希望它可以帮助某人。

【讨论】:

【参考方案3】:

斯威夫特 5

我是这样做的:

let vc = viewControllerToDisplay()
let navVc = UINavigationController(rootViewController: vc)

navVc.modalPresentationStyle = .overCurrentContext
navVc.modalTransitionStyle = .crossDissolve

navigationController?.present(navVc, animated: true, completion: nil)

【讨论】:

以上是关于使用 overCurrentContext 呈现视图控制器,然后推送到导航堆栈会导致导航栏重叠的主要内容,如果未能解决你的问题,请参考以下文章

使用 UIModalPresentationStyle.OverCurrentContext 在 ViewController 之上的 UITransitionView

呈现全屏时的透明视图控制器背景

如何在ViewController2.swift类的overCurrentContext视图中显示图像?

containerView的自定义动画中的modalPresentationStyle .overCurrentContext返回黑屏

模态视图导航栏未正确显示

无法关闭视图控制器