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

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

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

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

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

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

谢谢!

【问题讨论】:

标签: ios objective-c uiviewcontroller uinavigationbar popupwindow


【解决方案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 度旋转出现。似乎是他们在这里谈论的内容:stackoverflow.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;
                      

                      希望对您有所帮助!

                      【讨论】:

                      • 谢谢,但我认为缺少一些东西,因为什么都没有出现:/
                      猜你喜欢
                      • 2018-06-22
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2016-08-11
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多