首先添加UIView,甚至导航栏


181

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

  • 全屏黑色背景,带有0.5 alpha值,以查看UIViewController下面的其他内容。
  • UIView中间有一些信息的窗口(如果您想了解所有内容,则为日历)。

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

我试图将其表示为模态,但UIViewController下面的内容消失了,并且失去了透明效果。

任何想法做到这一点,我相信这很简单...

谢谢!


在您的应用程序窗口中添加一个子视图。处理方向的变化可能会非常棘手:stackoverflow.com/questions/8774495/...
阿马尔

Answers:


197

您可以通过将视图直接添加到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)

2
谢谢:)不幸的是,如果您处于横向模式,则需要旋转视图。我不确定我是否知道如何正确地做到这一点。
Nicolas Roy 2014年

是的,我仅处于横向模式,并且myView会旋转90度。似乎正是他们在谈论这里:stackoverflow.com/questions/8774495/...
尼古拉斯·罗伊

定向问题发生在iOS8之前的设备上,遗憾的是该解决方案不起作用。
thgc 2014年

@NicolasRoy Autolayout将有所帮助
Darmen Amanbayev

4
它不覆盖标签栏。有什么解决办法吗?
Manisha

134

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


5
您需要设置框架
Gabriel Goncalves 2015年

1
很好的解决方案,尤其是当您将视图添加为“子视图控制器”时
Richard Topchii 2015年

2
这不适用于子视图控制器的视图。更改导航栏的z级别(如Nam所建议)也适用于子视图控制器。
Tapani 2015年

与向“关键点”窗口添加视图相比,它看起来是一种更优雅的解决方案。这样可以确保添加视图,然后沿基本视图的动画移动。因为如果在关键窗口上添加了视图,则该视图不附带动画,因此如果要关闭控制器,则必须单独将其删除。
soan saini

这不是弹出窗口,但这对我来说是正确的事情。谢谢))
Dilshod Zopirov

112

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

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

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


1
这比将叠加视图作为子视图添加到导航控制器的视图(顺便造成崩溃)要好得多。此z位置解决方案可能更可靠,并且将来引起的问题更少。
Tapani,2015年

使用情节提要板时,这非常有用。您可以在情节提要中添加视图!
Jos Koomen

对我也很好。值得一提的是,应该将zPosition的值重新设置为0(您刚刚提到完成后应该将其重新设置)。而且我的TabBar(从TabBarController在我的屏幕我也试图设置z位置,但返回到0值的TabBar时仍然不可见,所以对于它的TabBar最好使用是否隐藏属性。
伦敦银行同业拆借利率Zapletal

1
不要使用可访问性。平移视图不会使其聚焦。
antonjn

我爱你!!<3
chr0x

57

所检查响应的Swift版本:

斯威夫特4:

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

Swift 3.1:

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

6
我可以覆盖所有当前视图(视图控制器),但在其上方保留新出现的视图控制器吗?
米哈尔Ziobro

24

将您添加为NavigationController的子视图。

[self.navigationController.navigationBar addSubview: overlayView)]

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

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

希望这可以帮助.. :)


即将到来的视图,但是,当添加按钮时,无法在overView上执行按钮操作或设置自定义标签文本
Vineesh TP

为我工作正常:let navigationBar = viewController.navigationController!.navigationBar navigationBar.addSubview(coverView)
Arthur Clemens

22

Dalef快速解决方案:

self.navigationController?.view.addSubview(view)

11

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

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()

1
完美的解决方案。尝试了很多东西,花了很多时间..但这很好.. !!
Dishant

8

@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
}

不要忘记窗口必须是坚固的属性,因为原始答案会导致窗口立即被重新分配


6

我建议您创建一个新的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;

希望对您有所帮助!


3
谢谢,但我认为由于缺少任何内容而缺少了一些东西:/
Nicolas Roy

6

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

1-在UIView上添加您的内容,UIWindow而不是在上添加UIViewController。这样,它将是一切的基础。

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

2-使用自定义过渡,这将使您的UIViewController在背面显示0.5 alpha

为此,我建议您看一下:https : //github.com/Citrrus/BlurryModalSegue


4
[[UIApplication sharedApplication].windows.lastObject addSubview:myView];

2

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

添加这些扩展UIViewController中

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()
}

2

在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 you view name

1

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

请参阅实现容器视图控制器


1
UIApplication.shared.keyWindow?.insertSubview(yourView, at: 1)

此方法适用于xcode 9.4,iOS 11.4


0
[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];

在此处输入图片说明


0

您需要使用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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.