Uiwindow with Wrong Size When Using Landscape Orientation

UIWindow with wrong size when using landscape orientation

When you run landscape app from portrait mode UIScreen has portrait bounds in iOS 8 (only if you haven't this app in app switch panel, as iOS 8 makes some cache). Even displaying window with makeKeyAndVisible doesn't change it's frame. But it changes [UIScreen mainScreen].bounds according to AppViewController avaliable orientation.

#import "AppDelegate.h"
#import "AppViewController.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Portrait bounds at this point
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

self.window.backgroundColor = [UIColor cyanColor];
self.window.rootViewController = [[AppViewController alloc] init];
[self.window makeKeyAndVisible];
return YES;
}

@end

So let's change window's frame after [self.window makeKeyAndVisible]

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [UIWindow new];
self.window.backgroundColor = [UIColor cyanColor];
self.window.rootViewController = [[AppViewController alloc] init];
[self.window makeKeyAndVisible];

// Here it is
self.window.frame = [UIScreen mainScreen].bounds;
return YES;
}

I think that it is iOS 8 bug.

UIWindow orientation issues (two UIWindows and landscape mode)

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=✓

Newly created UIWindow is sideways when app is opened on landscape

As far as I understood, newly created UIWindow's do not rotate automatically when the orientation changes. I don't know whether this is new to iOS 8 or if it is a bug, but I was able to overcome the problem with the following piece of code:

UIWindow *window=[UIApplication sharedApplication].keyWindow;
self.progressWindow = [[UIWindow alloc] initWithFrame:window.frame];
self.progressWindow.backgroundColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f];
self.progressWindow.windowLevel = UIWindowLevelAlert;

/* some other code to create the subviews */

[self handleOrientationChange];
[self.progressWindow makeKeyAndVisible];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleOrientationChange) name:UIApplicationDidChangeStatusBarFrameNotification object:nil];

Implementation for handleOrientationChange is as follows:

#define DegreesToRadians(degrees) (degrees * M_PI / 180)

- (void)handleOrientationChange
{
if (self.progressWindow)
{
// rotate the UIWindow manually
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
[self.progressWindow setTransform:[self transformForOrientation:orientation]];

// resize the UIWindow according to the new screen size
if ([[UIScreen mainScreen] respondsToSelector:@selector(nativeBounds)])
{
// iOS 8
CGRect screenRect = [UIScreen mainScreen].nativeBounds;
CGRect progressWindowFrame = self.progressWindow.frame;
progressWindowFrame.origin.x = 0;
progressWindowFrame.origin.y = 0;
progressWindowFrame.size.width = screenRect.size.width / [UIScreen mainScreen].nativeScale;
progressWindowFrame.size.height = screenRect.size.height / [UIScreen mainScreen].nativeScale;
self.progressWindow.frame = progressWindowFrame;
}
else
{
// iOs 7 or below
CGRect screenRect = [UIScreen mainScreen].bounds;
CGRect progressWindowFrame = self.progressWindow.frame;
progressWindowFrame.origin.x = 0;
progressWindowFrame.origin.y = 0;
progressWindowFrame.size.width = screenRect.size.width;
progressWindowFrame.size.height = screenRect.size.height;
self.progressWindow.frame = progressWindowFrame;
}
}
}

- (CGAffineTransform)transformForOrientation:(UIInterfaceOrientation)orientation {

switch (orientation) {

case UIInterfaceOrientationLandscapeLeft:
return CGAffineTransformMakeRotation(-DegreesToRadians(90));

case UIInterfaceOrientationLandscapeRight:
return CGAffineTransformMakeRotation(DegreesToRadians(90));

case UIInterfaceOrientationPortraitUpsideDown:
return CGAffineTransformMakeRotation(DegreesToRadians(180));

case UIInterfaceOrientationPortrait:
default:
return CGAffineTransformMakeRotation(DegreesToRadians(0));
}
}

I got the idea from the accepted answer of this question.

Wrong bounds when portrait iPhone app launched on iPad with landscape orientation

A workaround is to switch the bounds width and height if the window starts with a none portrait orientation.

func scene(_ scene: UIScene, willConnectTo _: UISceneSession, options _: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let windowScene = (scene as? UIWindowScene) else { return }

var bounds = windowScene.coordinateSpace.bounds
let isPortrait = windowScene.interfaceOrientation.isPortrait

if !isPortrait {
let width = bounds.height
let height = bounds.width

bounds = CGRect(x: 0, y: 0, width: width, height: height)
}

window = UIWindow(frame: bounds)
window?.windowScene = windowScene
window?.rootViewController = MyViewController()
window?.makeKeyAndVisible()
}


Related Topics



Leave a reply



Submit