Add a UIView above all, even the navigation bar

IosObjective CUiviewcontrollerUinavigationbarPopupwindow

Ios Problem Overview


I want to display, above any other views, even the navigation bar, a kind of "pop-up" view that looks like this:

  • full screen black background with a 0.5 alpha to see the other UIViewController underneath.
  • a UIView window in the middle with some information, (a calendar if you want to know everything).

To do that, I've created a UIViewController that contains the two UIViews (background and window), and I'm trying to display it. I've tried a simple [mySuperVC addSubview:myPopUpVC.view], but I still have the navigation bar above.

I've tried to present it as a modal, but the UIViewController underneath disappears, and I lose my transparency effect.

Any idea to do this, I'm sure it's quite simple...

Thanks!

Ios Solutions


Solution 1 - Ios

You can do that by adding your view directly to the keyWindow:

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

UPDATE -- For Swift 4.1 and above

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

UPDATE for iOS13 and above

keyWindow is deprecated. You should use the following:

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

Solution 2 - Ios

[self.navigationController.view addSubview:overlayView]; is what you really want

Solution 3 - Ios

Here is a simple elegant solution that is working for me. You can set the z position of the navigation bar to below the view:

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

Just remember to set it back to 0 when done.

Solution 4 - Ios

Swift versions for the checked response :

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)

Solution 5 - Ios

Dalef great solution in swift:

self.navigationController?.view.addSubview(view)

Solution 6 - Ios

Add you view as the subview of NavigationController.

[self.navigationController.navigationBar addSubview: overlayView)]

You can also add it over the window:

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

Hope this helps.. :)

Solution 7 - Ios

@Nam's answer works great if you just want to display your custom view but if your custom view needs user interaction you need to disable interaction for the navigationBar.

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

Like said in Nam's answer don't forget to reverse these changes:

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


You can do this in a better way with an extension:

extension UINavigationBar {
    func toggle() {
        if self.layer.zPosition == -1 {
            self.layer.zPosition = 0
            self.isUserInteractionEnabled = true
        } else {
            self.layer.zPosition = -1
            self.isUserInteractionEnabled = false
        }
    }
}

And simply use it like this:

self.navigationController.navigationBar.toggle()

Solution 8 - Ios

Swift version of @Nicolas Bonnet 's answer:

    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
}

Don't forget that the window must be a strong property, because the original answer leads to an immediate deallocation of the window

Solution 9 - Ios

I recommend you to create a new 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];

Then you can manage your view in an other UIViewController. To remove the windows:

[window removeFromSuperview];
window = nil;

hope that will help!

Solution 10 - Ios

There is more than one way to do it:

1- Add your UIView on UIWindow instead of adding it on UIViewController. This way it will be on top of everything.

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

2- Use custom transition that will keep your UIViewController showing in the back with a 0.5 alpha

For that I recommend you look at this: https://github.com/Citrrus/BlurryModalSegue

Solution 11 - Ios

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

Solution 12 - Ios

In Swift 4.2 and 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!)

In Objective C

UIView *spinnerView;//This is your view

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

This can work either Portrait OR Landscape mode.

One more simple code is:

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

Solution 13 - Ios

Note if you want add view in Full screen then only use below code

Add these extension of 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
      }
   }
}

Continue as normal adding process of subview

Now use in adding UIViewController's viewDidAppear

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    
     self.makeViewAsFullScreen()
}

Solution 14 - Ios

I'd use a UIViewController subclass containing a "Container View" that embeds your others view controllers. You'll then be able to add the navigation controller inside the Container View (using the embed relationship segue for example).

See Implementing a Container View Controller

Solution 15 - Ios

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

This method works with xcode 9.4 , iOS 11.4

Solution 16 - Ios

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

enter image description here

Solution 17 - Ios

You need to add a subview to the first window with the UITextEffectsWindow type. To the first, because custom keyboards add their UITextEffectsWindow, and if you add a subview to it this won't work correctly. Also, you cannot add a subview to the last window because the keyboard, for example, is also a window and you can`t present from the keyboard window. So the best solution I found is to add subview (or even push view controller) to the first window with UITextEffectsWindow type, this window covers accessory view, navbar - everything.

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)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNicolas RoyView Question on Stackoverflow
Solution 1 - IosRom.View Answer on Stackoverflow
Solution 2 - IosdalefView Answer on Stackoverflow
Solution 3 - IosNamView Answer on Stackoverflow
Solution 4 - IosKevin ABRIOUXView Answer on Stackoverflow
Solution 5 - IosAllreadyhomeView Answer on Stackoverflow
Solution 6 - IosRashadView Answer on Stackoverflow
Solution 7 - IosHemangView Answer on Stackoverflow
Solution 8 - IosiOS UnitView Answer on Stackoverflow
Solution 9 - IosNicolas BonnetView Answer on Stackoverflow
Solution 10 - IosDaniView Answer on Stackoverflow
Solution 11 - IosjoldView Answer on Stackoverflow
Solution 12 - IosNareshView Answer on Stackoverflow
Solution 13 - IosParesh NavadiyaView Answer on Stackoverflow
Solution 14 - IosdulganView Answer on Stackoverflow
Solution 15 - IosAhmed R.View Answer on Stackoverflow
Solution 16 - IosFadi AbuzantView Answer on Stackoverflow
Solution 17 - IosViktoriaView Answer on Stackoverflow