17

I am trying to make a popup (UIView) with a transparent background (another UIView). Everything is working fine for the 'popup UIView' but I couldn't figure out how to bring 'transparent background UIView' (above NavigationBar and TabBar).

First I created the UIView in the Storyboard and connected the outlet:

popupView.center = CGPointMake(CGRectGetMidX(self.view.bounds), tableView.center.y);
self.view.addSubview(popupView)
popupView.clipsToBounds = true
popupView.alpha = 0

Then, while displaying popupView I am creating the transparent background UIView:

 func clicked() {
    self.popupView.alpha = 1

    let screenSize: CGRect = UIScreen.mainScreen().bounds
    let opaqueView = UIView()
    opaqueView.frame.size = CGSize(width: screenSize.width, height: screenSize.height)
    opaqueView.backgroundColor = UIColor.blackColor()
    opaqueView.alpha = 0.5

    self.view.addSubview(opaqueView)
 }

However, the background view doesn't get over NavigationBar or TabBar. I tried this but nothing changes:

myTabBar.view.bringSubviewToFront(opaqueView)

What I want to achieve is that, while having popup UIView at the very front, having opaque UIView over everything including NavBar and TabBar, but behind popup UIView


Update:

Regarding @Alex's answer, with this chunk, I achieved displaying opaqueView over TabBar & NavBar; but now it's also going above the popupView.

func display() {
   popupView.center = CGPointMake(CGRectGetMidX(self.view.bounds), tableView.center.y);
    self.view.addSubview(popupView)
    popupView.clipsToBounds = true

    let opaqueView = UIView()
    let screenSize: CGRect = UIScreen.mainScreen().bounds
    opaqueView.frame.size = CGSize(width: screenSize.width, height: screenSize.height)
    UIApplication.sharedApplication().keyWindow!.insertSubview(opaqueView, belowSubview: popupView) 
}

How can I place opaqueView below popupView while opaqueView is above everything else?

senty
  • 12,385
  • 28
  • 130
  • 260

6 Answers6

14

Try this:

UIApplication.sharedApplication().keyWindow!.bringSubviewToFront(opaqueView)

Updating for Swift 4.2

 UIApplication.shared.keyWindow!.bringSubview(toFront: opaqueView!)

Updating for Swift 5

UIApplication.shared.keyWindow!.bringSubviewToFront(opaqueView!)
GGirotto
  • 848
  • 2
  • 10
  • 31
Alex Kosyakov
  • 2,095
  • 1
  • 17
  • 25
  • 1
    I tried this too, it's bringing the opaqueView over popupView (which I don't want), and doesn't bring it over NavBar and TabBar. Unfortunately, your answer doesn't help :/ – senty May 31 '16 at 18:21
  • 6
    To make it work you should add your opaqueView like this: UIApplication.sharedApplication().keyWindow!.addSubview(opaqueView); Then opaque view will be on the top of your subviews. You can't add it to your view (self.view.addSubview(opaqueView)) and wait for displaying it over navigation bar and tab bar. One of other solutions is to add it to tabbarController.view or navigationController.view. – Alex Kosyakov May 31 '16 at 18:31
  • 1
    Works like charm. Thanks a lot. But I have a question. When I use `UIApplication.sharedApplication().keyWindow!.addSubview(opaqueView);` opaqueView gets over popUpView. I tried using `opaqueView.bringSubviewToFront(popupView)`, but doesn't change anything. How can I bring 'popUpView' above 'opaqueView'? – senty May 31 '16 at 18:36
  • You can use insertSubview..belowSubview or insertSubview..aboveSubview methods, but in this case you should add your subviews to the same view. – Alex Kosyakov May 31 '16 at 18:47
  • First I tried `UIApplication.sharedApplication().keyWindow!.addSubview(popupView)`. This didn't change anything. Then, `opaqueView.insertSubview(popupView, atIndex: 1)`, however, it's also making the popupView transparent (opaqueView's 0.5 `.alpha` affects popupview). I am stuck :/ What can be the solution? – senty May 31 '16 at 18:53
  • Also tried `UIApplication.sharedApplication().keyWindow!.bringSubviewToFront(popupView)` but this also keeps opaqueView at the top – senty May 31 '16 at 19:00
  • UIApplication.sharedApplication().keyWindow!.addSubview(popupView) UIApplication.sharedApplication().keyWindow!.insertSubview(opaqueView belowSubview: popupView) – Alex Kosyakov May 31 '16 at 19:03
  • Using this causes opaqueView above popupView too :/ – senty May 31 '16 at 19:35
  • Are you sure you not using insert..aboveSubview method? And I forgot to write in this causes you don't need to call bringSubviewToFront function – Alex Kosyakov May 31 '16 at 19:38
  • I got confused. What should I write exactly? Can you please come to chatroom? [Let's continue this conversation in chatroom](http://chat.stackoverflow.com/rooms/113447/discussion-between-senty-and-alex-kosyakov).. This is what I exactly tried `UIApplication.sharedApplication().keyWindow!.insertSubview(opaqueView, belowSubview: popupView)` – senty May 31 '16 at 19:56
  • Answered you in the chatroom – Alex Kosyakov May 31 '16 at 20:53
8

UIApplication.shared.keyWindow!.bringSubviewToFront(view: view) was depreciated after iOS 13. The best way to have your transparent view cover both the tab controller and nav controller is by doing this.

if let tabBarController = self.tabBarController {
    tabBarController.view.addSubview(view)
}
F. Morales
  • 437
  • 6
  • 5
6

(swift 3+) This will make your view on top of tab bar and navigation bar

UIApplication.shared.keyWindow!.addSubview(yourView)
UIApplication.shared.keyWindow!.bringSubview(toFront: yourView)
Daniel Raouf
  • 2,307
  • 1
  • 22
  • 28
5
    func addButtonTapped(){
              if self.transparentBackground == nil{
                  self.transparentBackground = UIView(frame: UIScreen.main.bounds)
                  self.transparentBackground.backgroundColor = UIColor(white: 0.0, alpha: 0.54)
                  UIApplication.shared.keyWindow!.addSubview(self.transparentBackground)
                  self.opaqueView = self.setupOpaqueView()
                  self.transparentBackground.addSubview(opaqueView)
                  UIApplication.shared.keyWindow!.bringSubview(toFront: self.transparentBackground)
                  self.view.bringSubview(toFront: transparentBackground)
              }
          }

          func setupOpaqueView() -> UIView{
                let mainView = UIView(frame: CGRect(x: 16, y: 100, width: Int(UIScreen.main.bounds.width-32), height: 200))
                mainView.backgroundColor = UIColor.white
                let titleLabel = UILabel(frame: CGRect(x: 16, y: 20, width: Int(mainView.frame.width-32), height: 100))
                titleLabel.text = "This is the opaque"
                titleLabel.textAlignment = .center
                titleLabel.font = font
                titleLabel.textColor = UIColor(white: 0.0, alpha: 0.54)
                mainView.addSubview(titleLabel)


                let  OKbutton = UIButton(frame: CGRect(x: 16, y: Int(mainView.frame.height-60), width: Int(mainView.frame.width-32), height: 45))
                OKbutton.backgroundColor = UIColor(red: 40.0 / 255.0, green: 187.0 / 255.0, blue: 187.0 / 255.0, alpha: 1)
                OKbutton.layer.cornerRadius = 10
                mainView.addSubview(OKbutton)
                OKbutton.setTitle("OK", for: .normal)
                OKbutton.setTitleColor(UIColor.white, for: .normal)
                OKbutton.titleLabel?.font = font
                OKbutton.addTarget(self, action:  #selector(FirstViewController.handleOKButtonTapped(_:)), for: .touchUpInside)

                return mainView

          }

          func handleOKButtonTapped(_ sender: UIButton){
              UIView.animate(withDuration: 0.3, animations: {
                  self.transparentBackground.alpha = 0
              }) { done in
                  self.transparentBackground.removeFromSuperview()
                  self.transparentBackground = nil

              }
          }

preview of the result

Hackman
  • 2,629
  • 3
  • 18
  • 24
  • Hey @Hackman this is a great answer! How will you be able to apply a UITapGesture to the transparentBackground to dismiss the view, just the same like the OK button does but instead a UITapGesture. Thank you so much for your response – juelizabeth Jul 02 '17 at 02:02
  • 1
    Hey @juelizabeth, good question. To have the tap on the transparent view, create a UITapGestureRecognizer and add it to the addButtonTapped method. Just add these two lines to the addButtonTapped `let tap = UITapGestureRecognizer(target: self, action: #selector(FirstViewController.handleOKButtonTapped(_:))) self.transparentBackground.addGestureRecognizer(tap)` – Hackman Jul 05 '17 at 11:43
  • Thank you very much, this really helped – juelizabeth Jul 05 '17 at 14:31
  • what is transparentBackground? the app won't let me to run because the Value of type 'ViewController' has no member 'transparentBackground' – Saeed Rahmatolahi Jan 06 '18 at 08:01
  • 1
    @SaeedRahmatolahi the transparentBackground is a uiview property. declare inside the view controller – Hackman Jan 12 '18 at 14:32
5

Best solution is:

tabBarController?.view.addSubview(view)
Daniel
  • 475
  • 6
  • 10
-2

The view which you want to do transparent, use this

yourView.backgroundColor = UIColor.black.withAlphaComponent(0.7)

sumeet
  • 157
  • 1
  • 5