29

I'm wanting to create a view (UIControl) which blocks all input and shows a UIActivityIndicatorView while authenticating a user.

The UIActionSheet and UIAlertView both manage to add a black semi-transparent view over the top of all other views to block input and I'd like to do similar.

I've tried adding my view to the top UIWindow in the [[UIApplication sharedApplication] windows] array, and while this does place it above the UIKeyboard if it's visible, it doesn't place it over the StatusBar (which makes sense).

My next attempt was to extend UIAlertView, remove all of its subviews and set its layer.contents = nil, then add the ActivityIndicator as a subview. This works well, but I can't seem to kill the default bouncy transition of the UIAlertView when you call it to "show".

Does anyone have any pointers towards the best way tackle this problem that gives me full control?

Oh and I know blocking input is not great but I do ensure it's for a short period of time and it has the benefit of making it clear to the user that their action, which must complete for them to progress, is processing.

Mike
  • 1,648
  • 1
  • 16
  • 15
  • 2
    Why "cover" the status bar? Why not hide it, have it be translucent, or just ignore it entirely? The status bar doesn't respond to touches, if I recall correctly. – Joseph Beckenbach Apr 19 '10 at 14:29
  • 5
    I'm wanting it to look like it is under the overlay view. This makes it clear to the user that they can not interact currently. Making it translucent does not achieve this unfortunately, and hiding it would look strange if just for the duration of authentication. And it does indeed respond to touches. The default is to scroll active UIScrollView to the top. – Mike Apr 19 '10 at 22:16

3 Answers3

52

I've done some more digging around the API's and believe I've worked it out.

In order to display a view over the entire screen you need to create your own UIWindow and set its windowLevel property to be UIWindowLevelStatusBar. You can then add your custom subviews to this window.

Note that Apple does not encourage, but neither do they prohibit the creation of multiple windows.

UIWindow *statusWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
statusWindow.windowLevel = UIWindowLevelStatusBar;
statusWindow.hidden = NO;
statusWindow.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.7];
[statusWindow makeKeyAndVisible];

When you want to remove the window from the screen it looks as though you release it from memory.

[statusWindow release];

This doesn't feel totally safe, but I don't get any errors and it seems to drop it out of the UIApplication's windows array. Please let me know if this is wrong.

Update:

One other issue I came across was the UIStatusBar not taking touch events to scroll the active UIScrollView to the top after I had displayed and removed this overlay window. The solution was to set the primary window back to the key window once the overlay had been released.

[primaryWindow makeKeyWindow];
Maulik
  • 19,348
  • 14
  • 82
  • 137
Mike
  • 1,648
  • 1
  • 16
  • 15
  • 2
    This code doesn't work for me in iOS 4.2. The status window will appear, but not over the default statusbar provided by the OS. Any tips? Is this still working for you as of iOS 4.2? – jbrennan Dec 02 '10 at 00:55
  • It works, but when I present a viewController animated, my this window, which has an activity indicator goes behind the presented viewController, any solutions to this problem? – Raj Pawan Gumdal Jan 17 '12 at 15:00
  • 1
    this failed when Im trying to rotate the interface to the landscape orientation.the statusWindow just stick to the origin status bar position. – Carusd Ray Feb 21 '12 at 09:20
  • If you don't need your window to receive other non-touch events (keyboard events, etc) you can just skip the `makeKeyWindow` and `makeKeyAndVisble`. `statusWindow.hidden = NO;` should be enough. – nacho4d Jun 19 '12 at 06:55
  • @CarusdRay orientation must be handled by yourself. That is what happens when adding things directly to an UIWindow. You could create a subclass of UIWindow and make it automatically update itself according to the status bar orientation. FWIW Apple seems to do the same thing with the keyboard window (UITextEffectsWindow that inherits from UIAutoRotatingWindow https://github.com/kennytm/iphone-private-frameworks/blob/master/UIKit/UITextEffectsWindow.h) – nacho4d Jun 19 '12 at 07:02
  • Great solution, and yes you don't need makeKeyAndVisible to get the new window to show. – Abduliam Rehmanius Jan 16 '13 at 13:54
  • Problem: after I release the new window, it does disappear, but the original window (the initial key window created in app delegate) does no longer respond to any touch events, tried makeAndVisible on main window?? and Idea? Also keyboard was visible when new window was created! I am working on finding the problem but if someone has any idea about this please share, thans :) – Abduliam Rehmanius Jan 16 '13 at 13:56
  • 2
    Important to note that with ARC UIWindow *statusWindow can't be an instance variable otherwise it will be released right away - meaning it will never show up. – N S Nov 16 '13 at 00:02
  • 1
    It does not work when the keyboard is on the screen. The window appears below the keyboard. – Rafał Sroka Mar 25 '14 at 14:00
5

I needed to present a view on top of all other views within my main window. Initially, I thought of presenting another window on top of my key window. Since, apple discourages using multiple windows, I decided against it.

The following code did the trick for me:

I added my view as a sub view to my key window which automatically presents my view on top of all other views. In my case this code is in app's delegate

[self.window addSubview:topViewController.view]

And when I am done with the view, the following code removes it from the window.

[topViewController.view removeFromSuperview];
Vishal Chaudhry
  • 2,834
  • 1
  • 22
  • 8
1

I'm about to do the same thing shortly and found the following

http://www.dejal.com/developer/dsactivityview

Looks like it has everything you're looking for

Liam
  • 7,762
  • 4
  • 26
  • 27
  • Thanks for the link but this does not cover the status bar from what I can see. I'm after a semi-transparent view that will cover the entire area the UI. – Mike Apr 19 '10 at 12:28