Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIWindow orientation issues (two UIWindows and landscape mode)

I know that this looks like a huge question but it's not so don' be afraid to read it. Mostly it's me explaining how stuff works.

I have two UIWindows in my app. The first one is the main window which gets created by the app by default. The second one is called modalWindow and is also created in the app delegate.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.


    self.modalWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.modalWindow.windowLevel = UIWindowLevelStatusBar;

    //Other stuff I need
    //....

    return YES;
}

Most of my app is portrait only but there is one view controller where the user can switch to landscape orientation. I'm listening for landscape change via:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];

This works fine and in the orientationChanged method I present the landscape view controller. All is well at this point. If I rotate back to portrait I get the orientationChanged fired once more at which point I dismiss the landscape view controller.

Now let's explain how the second window comes into play. When in landscape mode there is an action (just a button press) which presents a new view controller on the second window (the modalWindow). Ok let's explain this.

The app delegate has two methods which look like so:

- (void)presentActivityOnModalWindow:(UIViewController *)viewController
{
    self.modalWindow.rootViewController = viewController;
    self.modalWindow.hidden = NO;
}

- (void)modalTransitionFinished:(NSNotification *)notif
{
    self.modalWindow.hidden = YES;
    self.modalWindow.rootViewController = nil;
}

I call the presentActivityOnModalWindow via the [[[UIApplication sharedApplication] delegate] performSelector....]. I know it isn't the best practice but it works fine. As for the dismissal I use NSNotificationCenter to post the notification about dismissal. The view controller that gets presented on the modalWindow is supporting only portrait mode. It's returning YES in shouldAutorotate and UIInterfaceOrientationMaskPortrait in supportedInterfaceOrientations.

Ok a lot of explaining but now we get to the problem. When I rotate to landscape, pop up the modalWindow, dismiss the modal window and rotate back to portrait my main window is still in landscape mode and everything looks catastrophic.

I tried adding an observer to both window and modalWindow and logging changes in frame and bounds and here are the results:

Did finish launching:
window frame {{0, 0}, {320, 568}}
window bounds {{0, 0}, {320, 568}}
modalWindow frame {{0, 0}, {320, 568}}
modalWindow bounds {{0, 0}, {320, 568}}

Rotate to landscape:
window frame {{0, 0}, {568, 320}}

Open activity in landscape:
modalWindow frame {{0, 0}, {320, 568}}
modalWindow frame {{0, 0}, {320, 568}}

Dismiss activity:
none


Rotate back to portrait:
none

So as it seems my window does not get back to normal frame when we get back to portrait mode. How to fix this? If I need to provide any more details feel free to ask.

like image 214
Majster Avatar asked Feb 20 '15 09:02

Majster


1 Answers

The system will only handle rotation of your keyWindow. If you have other windows you'll have to handle rotation yourself.

I also think that modal controllers is the way to go. But if you really want to handle rotations take a look at how other "custom windows" libraries handle rotation. Alert views are a great example:

https://github.com/search?o=desc&q=uialertview&s=stars&type=Repositories&utf8=✓

like image 136
Rivera Avatar answered Jan 03 '23 16:01

Rivera