首先添加一个 UIView,甚至是导航栏

Posted

技术标签:

【中文标题】首先添加一个 UIView,甚至是导航栏【英文标题】:Add a UIView above all, even the navigation bar 【发布时间】:2014-03-18 00:13:51 【问题描述】:

我想在任何其他视图甚至导航栏上方显示一种“弹出”视图,如下所示:

带有 0.5 alpha 的全屏黑色背景可以看到下面的另一个 UIViewController。 中间有一个 UIView 窗口,其中包含一些信息(如果您想了解所有信息,可以使用日历)。

为此,我创建了一个 UIViewController,其中包含两个 UIViews(背景和窗口),并且我正在尝试显示它。我尝试了一个简单的[mySuperVC addSubview:myPopUpVC.view],但我仍然有上面的导航栏。

我尝试将其呈现为模态,但下方的 UIViewController 消失了,我失去了透明效果。

任何想法,我相信这很简单......

谢谢!

【问题讨论】:

在您的应用程序窗口中添加子视图。处理方向变化可能很棘手:***.com/questions/8774495/… 【参考方案1】:

在 Swift 4.2 和 Xcode 10 中

var spinnerView: UIView? //This is your view

spinnerView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height))
//Based on your requirement change width and height like self.view.bounds.size.width
spinnerView?.backgroundColor = UIColor.black.withAlphaComponent(0.6)
//        self.view.addSubview(spinnerView)
let currentWindow: UIWindow? = UIApplication.shared.keyWindow
currentWindow?.addSubview(spinnerView!)

目标 C

UIView *spinnerView;//这是你的视图

self.spinnerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.height)];  
//Based on your requirement change width and height like self.view.bounds.size.width
self.spinnerView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
// [self.view addSubview:self.spinnerView];
UIWindow *currentWindow = [UIApplication sharedApplication].keyWindow;
[currentWindow addSubview:self.spinnerView];

这可以在纵向或横向模式下工作。

更简单的代码是:

yourViewName.layer.zPosition = 1//Change your view name

【讨论】:

【参考方案2】:

您可以通过将视图直接添加到 keyWindow 来做到这一点:

UIView *myView = /* <- Your custom view */;
UIWindow *currentWindow = [UIApplication sharedApplication].keyWindow;
[currentWindow addSubview:myView];

更新 -- 适用于 Swift 4.1 及更高版本

let currentWindow: UIWindow? = UIApplication.shared.keyWindow
currentWindow?.addSubview(myView)

适用于 iOS13 及更高版本的更新

keyWindow 已弃用。您应该使用以下内容:

UIApplication.shared.windows.first(where:  $0.isKeyWindow )?.addSubview(myView)

【讨论】:

谢谢 :) 不幸的是,如果您处于横向模式,您需要旋转视图。我不确定我是否知道如何正确地做到这一点。 是的,我只处于横向模式,myView 以 90 度旋转出现。似乎是他们在这里谈论的内容:***.com/questions/8774495/… 方向问题发生在 ios8 之前的设备上,遗憾的是这个解决方案不起作用。 @NicolasRoy Autolayout 会有所帮助 它不覆盖标签栏。有什么解决办法吗?【参考方案3】:

您需要在第一个窗口中添加一个 UITextEffectsWindow 类型的子视图。首先,因为自定义键盘添加了它们的 UITextEffectsWindow,如果你向它添加子视图,这将无法正常工作。 此外,您不能将子视图添加到最后一个窗口,因为例如键盘也是一个窗口,您不能从键盘窗口呈现。 所以我找到的最好的解决方案是将子视图(甚至推送视图控制器)添加到具有 UITextEffectsWindow 类型的第一个窗口,该窗口涵盖附件视图、导航栏 - 一切。

let myView = MyView()
myView.frame = UIScreen.main.bounds

guard let textEffectsWindow = NSClassFromString("UITextEffectsWindow") else  return 
let window = UIApplication.shared.windows.first  window in
    window.isKind(of: textEffectsWindow)

window?.rootViewController?.view.addSubview(myView)

【讨论】:

【参考方案4】:

已检查响应的 Swift 版本:

斯威夫特 4:

let view = UIView()
view.frame = UIApplication.shared.keyWindow!.frame
UIApplication.shared.keyWindow!.addSubview(view)

斯威夫特 3.1:

let view = UIView()
view.frame = UIApplication.sharedApplication().keyWindow!.frame 
UIApplication.sharedApplication().keyWindow!.addSubview(view)

【讨论】:

我可以让它覆盖所有当前视图(视图控制器),但让新出现的视图控制器显示在它上面吗?【参考方案5】:

如果您只想显示您的自定义视图,@Nam 的答案非常有用但如果您的自定义视图需要用户交互,您需要禁用navigationBar 的交互

self.navigationController.navigationBar.layer.zPosition = -1
self.navigationController.navigationBar.isUserInteractionEnabled = false

就像在 Nam 的回答中所说的那样,不要忘记扭转这些变化:

self.navigationController.navigationBar.layer.zPosition = 0
self.navigationController.navigationBar.isUserInteractionEnabled = true


您可以通过扩展以更好的方式做到这一点:
extension UINavigationBar 
    func toggle() 
        if self.layer.zPosition == -1 
            self.layer.zPosition = 0
            self.isUserInteractionEnabled = true
         else 
            self.layer.zPosition = -1
            self.isUserInteractionEnabled = false
        
    

然后像这样简单地使用它:

self.navigationController.navigationBar.toggle()

【讨论】:

完美解决方案.. !!尝试了很多东西并花了很多时间..但这很好..!!【参考方案6】:
UIApplication.shared.keyWindow?.insertSubview(yourView, at: 1)

此方法适用于 xcode 9.4、iOS 11.4

【讨论】:

【参考方案7】:

请注意,如果您想在全屏模式下添加视图,请仅使用以下代码

添加UIViewController

的这些extension
public extension UIViewController 
   internal func makeViewAsFullScreen() 
      var viewFrame:CGRect = self.view.frame
      if viewFrame.origin.y > 0 || viewFrame.origin.x > 0 
        self.view.frame = UIScreen.main.bounds
      
   

继续正常添加子视图

现在用于添加UIViewController的viewDidAppear

override func viewDidAppear(_ animated: Bool) 
    super.viewDidAppear(animated)

     self.makeViewAsFullScreen()

【讨论】:

【参考方案8】:

这是一个对我有用的简单优雅的解决方案。您可以将导航栏的z位置设置在视图下方:

self.navigationController.navigationBar.layer.zPosition = -1;

记得在完成后将其设置回 0。

【讨论】:

这比将覆盖视图作为子视图添加到导航控制器的视图(顺便说一下会导致崩溃)要好得多。这种 z 位置解决方案可能更可靠,并且在未来引起的问题更少。 这在处理故事板时非常有用。您可以在情节提要中添加视图! 对我也很有效。很高兴提到 zPosition 应该设置回值 0(您只是提到它应该在完成后设置回来)。而且我有 tabBar(在我的屏幕上也来自 TabBarController。我尝试设置 zPosition 但是当返回 0 值时 tabBar 仍然不可见。所以对于 tabBar 最好使用 isHidden 属性。 不要使用辅助功能。平移视图不会使其聚焦。【参考方案9】:
[self.navigationController.navigationBar.layer setZPosition:-0.1];
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(10, 20, 35, 35)];
[view setBackgroundColor:[UIColor redColor]];
[self.navigationController.view addSubview:view];
[self.navigationController.view bringSubviewToFront:view];
self.navigationController.view.clipsToBounds = NO;
[self.navigationController.navigationBar.layer setZPosition:0.0];

【讨论】:

【参考方案10】:
[[UIApplication sharedApplication].windows.lastObject addSubview:myView];

【讨论】:

【参考方案11】:

@Nicolas Bonnet 答案的 Swift 版本:

    var popupWindow: UIWindow?

func showViewController(controller: UIViewController) 
    self.popupWindow = UIWindow(frame: UIScreen.mainScreen().bounds)
    controller.view.frame = self.popupWindow!.bounds
    self.popupWindow!.rootViewController = controller
    self.popupWindow!.makeKeyAndVisible()


func viewControllerDidRemove() 
    self.popupWindow?.removeFromSuperview()
    self.popupWindow = nil

不要忘记窗口必须是一个强属性,因为原来的答案会导致窗口立即释放

【讨论】:

【参考方案12】:

将您的视图添加为 NavigationController 的子视图。

[self.navigationController.navigationBar addSubview: overlayView)]

您也可以在窗口上添加它:

UIView *view = /* Your custom view */;
UIWindow *window = [UIApplication sharedApplication].keyWindow;
[window addSubview:view];

希望这会有所帮助.. :)

【讨论】:

Over view 即将到来,但是,当添加按钮时无法获得按钮操作或在 overView 上设置自定义标签文本 对我来说很好:let navigationBar = viewController.navigationController!.navigationBar navigationBar.addSubview(coverView)【参考方案13】:

我会使用 UIViewController 子类,其中包含嵌入其他视图控制器的“容器视图”。 然后,您就可以在 Container View 中添加导航控制器(例如使用嵌入关系 segue)。

见Implementing a Container View Controller

【讨论】:

【参考方案14】:

Dalef 在 swift 中的绝佳解决方案:

self.navigationController?.view.addSubview(view)

【讨论】:

【参考方案15】:

有不止一种方法可以做到这一点:

1- 在UIWindow 上添加您的UIView,而不是在UIViewController 上添加它。这样一来,它将凌驾于一切之上。

   [[(AppDelegate *)[UIApplication sharedApplication].delegate window] addSubview:view];

2- 使用自定义过渡,让你的 UIViewController 以 0.5 alpha 显示在后面

为此,我建议您查看以下内容:https://github.com/Citrrus/BlurryModalSegue

【讨论】:

【参考方案16】:

[self.navigationController.view addSubview:overlayView]; 是你真正想要的

【讨论】:

你需要设置框架 非常好的解决方案,尤其是当您将视图添加为“子视图控制器”时 这不适用于子视图控制器的视图。更改导航栏的 z 级别(如 Nam 建议的那样)也适用于子视图控制器。 它看起来是一个比向 Key 窗口添加视图更优雅的解决方案。因为这确保了添加视图,所以沿着基本视图的动画移动。因为如果在关键窗口上添加视图,它不会附带动画,如果您想关闭控制器,则必须单独删除。 这不是弹出窗口,但它对我来说是正确的事情。谢谢))【参考方案17】:

我建议你创建一个新的 UIWindow:

UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
window.rootViewController = viewController;
window.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
window.opaque = NO;
window.windowLevel = UIWindowLevelCFShareCircle;
window.backgroundColor = [UIColor clearColor];

[window makeKeyAndVisible];

然后你可以在另一个 UIViewController 中管理你的视图。 移除窗户:

[window removeFromSuperview];
window = nil;

希望对您有所帮助!

【讨论】:

谢谢,但我认为缺少一些东西,因为什么都没有出现:/

以上是关于首先添加一个 UIView,甚至是导航栏的主要内容,如果未能解决你的问题,请参考以下文章

Push Segue 后在导航栏上添加 UIView

在 UITabBarController 中的标签栏和导航视图之间添加 UIView

如何在导航栏上添加UIView?

添加到 ScrollView 的 UIView 不适合全屏,顶部有导航栏

在导航控制器中添加子视图覆盖导航栏

如何制作一个可以覆盖导航栏的UIView?