I want to display, above any other views, even the navigation bar, a kind of "pop-up" view that looks like this:
UIViewController
underneath.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!
This question is related to
ios
uiviewcontroller
uinavigationbar
popupwindow
UIApplication.shared.keyWindow?.insertSubview(yourView, at: 1)
This method works with xcode 9.4 , iOS 11.4
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
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)
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.. :)
Dalef great solution in swift:
self.navigationController?.view.addSubview(view)
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!
[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];
@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
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()
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.
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)
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
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 only.
One more simple code is:
yourViewName.layer.zPosition = 1//Change you view name
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)
[[UIApplication sharedApplication].windows.lastObject addSubview:myView];
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).
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()
}
[self.navigationController.view addSubview:overlayView];
is what you really want
Source: Stackoverflow.com