Note: This may be a duplicate of Subview Doesnt AutoSize When Added to Root View Controller
I have an iPad app that switches between different views in its main window. The view-switching code looks like this:
- (void)switchToViewController:(UIViewController*)viewController {
if (currentViewController != viewController) {
[currentViewController.view removeFromSuperview];
currentViewController = viewController;
[window addSubview:viewController.view];
}
}
The problem is that when the new view (a UISplitView) appears in landscape orientation, it is not sized to fill the entire window. There is a large empty black space on the right. It looks like the view is only 768 pixels wide, rather than the 1024-pixel width of the landscape window.
If I rotate the device to portrait and then back to landscape, the view sizes itself properly.
If the device is in portrait orientation, everything works fine. The UISplitView also gets sized properly if it is the first view I show. The problem only occurs if I switch to it after another view has been shown, in landscape.
So, is there some way to force iPhone OS to resize the view after it has been added to the window?
I've tried calling sizeToFit
, and setNeedsLayout
. I've also tried setting the view's bounds
to the window's bounds
, and I've tried setting the frame
to match the previous view's frame.
This is absolutely possible! :-)
You can check out my repo here: https://github.com/hfossli/AGWindowView
It will automatically deal with any rotation and framechanges so you won't have to worry about that.
If you like to worry about that then you can just cut and paste the most important parts
# 1 Add view to window
[[UIApplication sharedApplication] keyWindow] addSubview:aView];
# 2 Add listener and update view
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarFrameOrOrientationChanged:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarFrameOrOrientationChanged:) name:UIApplicationDidChangeStatusBarFrameNotification object:nil];
Remember to remove notification listening
[[NSNotificationCenter defaultCenter] removeObserver:self];
# 3 Do the math
- (void)statusBarFrameOrOrientationChanged:(NSNotification *)notification
{
/*
This notification is most likely triggered inside an animation block,
therefore no animation is needed to perform this nice transition.
*/
[self rotateAccordingToStatusBarOrientationAndSupportedOrientations];
}
- (void)rotateAccordingToStatusBarOrientationAndSupportedOrientations
{
UIInterfaceOrientation statusBarOrientation = [UIApplication sharedApplication].statusBarOrientation;
CGFloat angle = UIInterfaceOrientationAngleOfOrientation(statusBarOrientation);
CGFloat statusBarHeight = [[self class] getStatusBarHeight];
CGAffineTransform transform = CGAffineTransformMakeRotation(angle);
CGRect frame = [[self class] rectInWindowBounds:self.window.bounds statusBarOrientation:statusBarOrientation statusBarHeight:statusBarHeight];
[self setIfNotEqualTransform:transform frame:frame];
}
- (void)setIfNotEqualTransform:(CGAffineTransform)transform frame:(CGRect)frame
{
if(!CGAffineTransformEqualToTransform(self.transform, transform))
{
self.transform = transform;
}
if(!CGRectEqualToRect(self.frame, frame))
{
self.frame = frame;
}
}
+ (CGFloat)getStatusBarHeight
{
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if(UIInterfaceOrientationIsLandscape(orientation))
{
return [UIApplication sharedApplication].statusBarFrame.size.width;
}
else
{
return [UIApplication sharedApplication].statusBarFrame.size.height;
}
}
+ (CGRect)rectInWindowBounds:(CGRect)windowBounds statusBarOrientation:(UIInterfaceOrientation)statusBarOrientation statusBarHeight:(CGFloat)statusBarHeight
{
CGRect frame = windowBounds;
frame.origin.x += statusBarOrientation == UIInterfaceOrientationLandscapeLeft ? statusBarHeight : 0;
frame.origin.y += statusBarOrientation == UIInterfaceOrientationPortrait ? statusBarHeight : 0;
frame.size.width -= UIInterfaceOrientationIsLandscape(statusBarOrientation) ? statusBarHeight : 0;
frame.size.height -= UIInterfaceOrientationIsPortrait(statusBarOrientation) ? statusBarHeight : 0;
return frame;
}
CGFloat UIInterfaceOrientationAngleOfOrientation(UIInterfaceOrientation orientation)
{
CGFloat angle;
switch (orientation)
{
case UIInterfaceOrientationPortraitUpsideDown:
angle = M_PI;
break;
case UIInterfaceOrientationLandscapeLeft:
angle = -M_PI_2;
break;
case UIInterfaceOrientationLandscapeRight:
angle = M_PI_2;
break;
default:
angle = 0.0;
break;
}
return angle;
}
UIInterfaceOrientationMask UIInterfaceOrientationMaskFromOrientation(UIInterfaceOrientation orientation)
{
return 1 << orientation;
}
Good luck!