Automatically Sizing UIView after Adding to Window - iphone

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!

This works, but it seems a little hacky:
- (void)switchToViewController:(UIViewController *)viewController {
if (viewController != currentViewController) {
UIInterfaceOrientation orientation = currentViewController.interfaceOrientation;
[currentViewController.view removeFromSuperview];
currentViewController = viewController;
UIView *view = viewController.view;
// Set appropriate view frame (it won't be autosized by addSubview:)
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
if (UIInterfaceOrientationIsLandscape(orientation)) {
// Need to flip the X-Y coordinates for landscape
view.frame = CGRectMake(appFrame.origin.y, appFrame.origin.x, appFrame.size.height, appFrame.size.width);
}
else {
view.frame = appFrame;
}
[window addSubview:view];
}
}

The window may include other UI elements besides your view. The 20 pixel difference in your example is the height of the status bar.
[[UIApplication sharedApplication] statusBarFrame].height;
Neither the window nor screen rotate. Getting their frames and using them for a rotated view will only work if you have switched the height and width.
If you are using a UIViewController, try returning YES from this method:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation; // Override to allow rotation. Default returns YES only for UIDeviceOrientationPortrait

I got the same problem, but i fixed it with this lines of code:
- (void)changeRow:(NSNotification *)notification {
[window addSubview:new.view];
[old.view removeFromSuperview];
[new.view removeFromSuperview];
[window addSubview:new.view];
}
You must add the new view, then remove the old and the new and then add the new view. I don't know why, but that works.

Fossli's answer is correct for iPad. However, I have a universal app that I needed to support. Therefore some adjustments are necessary.
Add the following to AppDelegate.h
#property (strong, nonatomic) UIImageView *imageView;
Add the following to AppDelegate.m
#synthesize imageView;
- (void)orientationChanged:(NSNotification *)notification
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (! (UIInterfaceOrientationIsLandscape(deviceOrientation) ||
UIInterfaceOrientationIsPortrait(deviceOrientation)))
{
// May be "UIInterfaceOrientationUnknown" which does not appear to be a defined value anywhere.
return;
}
[imageView setImage:[UIImage imageNamed:[Utility getBackgroundImageNameWithOrientation:deviceOrientation]]];
/*
iOS Image Sizes
iPhone/iPod Portrait 320 x 480 (640 x 960 #2x)
iPad Portrait 768 x 1004 (1536 x 2008 #2x)
Landscape 1024 x 748 (2048 x 1496 #2x)
iPad window bounds in both orientations 768 x 1024 (needs manual swap in landscape)
iPhone window bounds in both orientations 320 x 480 (needs manual swap in landscape)
Note the size variations between the required default launch image sizes and
the size of the window bounds.
iPhone/iPod only requires rotations.
iPad needs origin or size adjustments depending on orientation.
*/
CGFloat angle = 0.0;
CGRect newFrame = [[self window] bounds];
// How to get size of status bar
// Size of status bar gets all wonky on rotations so just set it manually
// CGSize statusBarSize = [[UIApplication sharedApplication] statusBarFrame].size;
CGSize statusBarSize = CGSizeMake(20.0, 20.0);
if (deviceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
angle = M_PI;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
newFrame.size.height -= statusBarSize.height;
}
}
else if (deviceOrientation == UIInterfaceOrientationLandscapeLeft)
{
angle = - M_PI / 2.0f;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
newFrame.origin.x += statusBarSize.height;
newFrame.size.width += statusBarSize.height;
}
}
else if (deviceOrientation == UIInterfaceOrientationLandscapeRight)
{
angle = M_PI / 2.0f;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
newFrame.size.width -= statusBarSize.height;
}
}
else
{
angle = 0.0;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
newFrame.origin.y += statusBarSize.height;
newFrame.size.height -= statusBarSize.height;
}
}
imageView.transform = CGAffineTransformMakeRotation(angle);
imageView.frame = newFrame;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Add background image to window with orientation changes so that it is visible in all views.
// A listener is added since subviews do not receive orientation changes.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object: nil];
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[Utility getBackgroundImageNameWithOrientation:deviceOrientation]]];
[[self window] addSubview:imageView];
return YES;
}
Add the following to Utility.h
+ (NSString *)getBackgroundImageNameWithOrientation:(UIDeviceOrientation)interfaceOrientation;
Add the following to Utility.m
+ (NSString *)getBackgroundImageNameWithOrientation:(UIDeviceOrientation)interfaceOrientation
{
NSString *imageName = nil;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
{
imageName = #"Default-Landscape~ipad.png";
}
else
{
imageName = #"Default-Portrait~ipad.png";
}
}
else
{
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
{
imageName = #"Default-Landscape~iphone.png";
}
else
{
imageName = #"Default.png";
}
}
return imageName;
}

Windows of iOS7 have different behaviors with windows of iOS8/9.
Keyboard window of iOS7 and all windows of iOS8/9 always have correct orientation & size. So you can observer the size change events and update the frame of your view.
But other windows of iOS7 always keep the portrait orientation and size. You need update transform of your view after rotation.
You need to observer UIApplicationWillChangeStatusBarOrientationNotification and update size of your UIView like this:
#interface MyView : UIView
#end
#implementation MyView
- (instancetype)init
{
if (self = [super init]) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(changeOrientationHandler:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
}
- (void)updateTransformWithOrientation:(UIInterfaceOrientation)orientation
{
CGFloat width = CGRectGetWidth(self.window.bounds);
CGFloat height = CGRectGetHeight(self.window.bounds);
if (width > height) {
CGFloat temp = width;
width = height;
height = temp;
}
CGFloat offset = (height - width) / 2;
CGAffineTransform transform;
switch (orientation) {
case UIInterfaceOrientationLandscapeLeft:
transform = CGAffineTransformMakeTranslation(-offset, offset);
transform = CGAffineTransformRotate(transform, -M_PI_2);
break;
case UIInterfaceOrientationLandscapeRight:
transform = CGAffineTransformMakeTranslation(-offset, offset);
transform = CGAffineTransformRotate(transform, M_PI_2);
break;
case UIInterfaceOrientationPortraitUpsideDown:
transform = CGAffineTransformMakeRotation(-M_PI);
break;
default:
transform = CGAffineTransformIdentity;
break;
}
self.transform = transform;
self.frame = CGRectMake(0, 0, width, height);
}
- (void)updateFrameWithOrientation:(UIInterfaceOrientation)orientation
{
CGFloat width = CGRectGetWidth(self.window.bounds);
CGFloat height = CGRectGetHeight(self.window.bounds);
if (width > height) {
CGFloat temp = width;
width = height;
height = temp;
}
switch (orientation) {
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
self.frame = CGRectMake(0, 0, height, width);
break;
default:
self.frame = CGRectMake(0, 0, width, height);
break;
}
}
- (void)updateWithOrientation:(UIInterfaceOrientation)orientation
{
BOOL isIos7 = [[UIDevice currentDevice].systemVersion floatValue] < 8.0;
BOOL isKeyboardWindow = [self.window isKindOfClass:NSClassFromString(#"UITextEffectsWindow")];
if (isIos7 == YES && isKeyboardWindow == NO) {
[self updateTransformWithOrientation:orientation];
} else {
[self updateFrameWithOrientation:orientation];
}
}
- (void)changeOrientationHandler:(NSNotification *)notification
{
[UIView animateWithDuration:0.25 animations:^{
UIInterfaceOrientation orientation = (UIInterfaceOrientation)[notification.userInfo[UIApplicationStatusBarOrientationUserInfoKey] integerValue];
[self updateWithOrientation:orientation];
}];
}
#end

Related

iphone's rotated view doesn't take up whole screen

I rotated a view using CGAffineTransformMakeRotation. ( iPhone - allow landscape orientation on just one viewcontroller )
As you can see below, the images have white region in left and right.
I want the image take up the whole space with black background.(at least in one dimension, width or height )
Below is the full code
- (void) viewDidLoad
{
[super viewDidLoad];
self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.view.backgroundColor = [UIColor blackColor];
self.imageView.backgroundColor = [UIColor blackColor];
self.imageView.opaque = NO;
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
self.imageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
[self.imageView setImageWithURL:[NSURL URLWithString:self.jsonAlbumImage.url_image
relativeToURL: [NSURL URLWithString:#URL_BASE]]
placeholderImage: [GlobalHelper placeHolderImage]];
[self.view addSubview: self.imageView];
}
- (void)didRotate:(NSNotification *)notification {
UIDeviceOrientation orientation = [[notification object] orientation];
if (orientation == UIDeviceOrientationLandscapeLeft) {
[self.view setTransform:CGAffineTransformMakeRotation(M_PI / 2.0)];
} else if (orientation == UIDeviceOrientationLandscapeRight) {
[self.view setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
} else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
[self.view setTransform:CGAffineTransformMakeRotation(M_PI)];
} else if (orientation == UIDeviceOrientationPortrait) {
[self.view setTransform:CGAffineTransformMakeRotation(0.0)];
}
}
-- EDIT --
What worked for me in the end .. don't know why modification does work.. any explanation would be great!
UIDeviceOrientation orientation = [[notification object] orientation];
CGAffineTransform t;
CGRect rect;
if (orientation == UIDeviceOrientationLandscapeLeft) {
t = CGAffineTransformMakeRotation(M_PI / 2.0);
rect = CGRectMake(0,0,480,320);
} else if (orientation == UIDeviceOrientationLandscapeRight) {
t = CGAffineTransformMakeRotation(M_PI / -2.0);
rect = CGRectMake(0,0,480,320);
} else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
t = CGAffineTransformMakeRotation(M_PI);
rect = CGRectMake(0,0,320,480);
} else if (orientation == UIDeviceOrientationPortrait) {
t = CGAffineTransformMakeRotation(0.0);
rect = CGRectMake(0,0,320,480);
}
else
return; // looks like there are other orientations than the specified 4
[self.view setTransform:t];
self.view.bounds = rect;
In - (void)didRotate:(NSNotification *)notification, you need to relayout your views so that they occupy all the space available. You could do something like this:
- (void)didRotate:(NSNotification *)notification {
UIDeviceOrientation orientation = [[notification object] orientation];
CGAffineTransform t;
if (orientation == UIDeviceOrientationLandscapeLeft) {
t = CGAffineTransformMakeRotation(M_PI / 2.0);
} else if (orientation == UIDeviceOrientationLandscapeRight) {
t = CGAffineTransformMakeRotation(M_PI / -2.0);
} else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
t = CGAffineTransformMakeRotation(M_PI);
} else if (orientation == UIDeviceOrientationPortrait) {
t = CGAffineTransformMakeRotation(0.0);
}
CGPoint screenCenter = CGPointMake([UIScreen mainScreen].bounds.width/2,[UIScreen mainScreen].bounds.height/2);
self.view.center = CGPointApplyAffineTransform(screenCenter, t);
self.view.bounds = CGRectApplyAffineTransform([UIScreen mainScreen].bounds, t);
[self.view setTransform:t];
}
Where :
CGRectApplyAffineTransform
Applies an affine transform to a rectangle.
CGRect CGRectApplyAffineTransform (
CGRect rect,
CGAffineTransform t
);
Try also removing this line:
self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
You don´t need it if you are not going to use autorotation and I fear it might conflict with your own setting the view's frame. This is just an hypothesis to account for the fact that you are not seeing the view´s frame change.
EDIT:
I'd very much like to know what this transform thing does
well, the transform is doing the rotation.
rotating is relative to an anchor point which is used as a pivot; what happens is that if the anchor point is not in the middle of the view being rotated, then the view is also translated (imagine a rotation around a vertex).
So, it is correct to set the bounds to make things even; indeed I was suggesting just that with the lines:
self.view.center = CGPointApplyAffineTransform(screenCenter, t);
self.view.bounds = CGRectApplyAffineTransform([UIScreen mainScreen].bounds, t);
but possibly the idea of applying the same transform to both the center and the bounds was not blessed. (that is also why I asked for some traces, to see what was happening :-)

UnifeyeMobileViewController glView camera view is not rotating in iPhone

in my iPhone application, I am using metaio sdk with UnfieyeMobileViewController. I have customized the view to show the camera view on the EAGLView component, and its works fine. The issue the when rotate the device, the camera orientation is not changing. And also, the captured image is showing upside down. Here is my code, please check:
In ViewDidAppear:
UIInterfaceOrientation interfaceOrientation = self.interfaceOrientation;
[self willAnimateRotationToInterfaceOrientation:interfaceOrientation duration:0];
[super viewDidAppear:animated];
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
// adjust the rotation based on the interface orientation
switch (interfaceOrientation) {
case UIInterfaceOrientationPortrait:
self.glView.transform = CGAffineTransformMakeRotation(0);
break;
case UIInterfaceOrientationPortraitUpsideDown:
self.glView.transform = CGAffineTransformMakeRotation(M_PI);
break;
case UIInterfaceOrientationLandscapeLeft:
self.glView.transform = CGAffineTransformMakeRotation(M_PI_2);
break;
case UIInterfaceOrientationLandscapeRight:
self.glView.transform = CGAffineTransformMakeRotation(-M_PI_2);
break;
}
// make sure the screen bounds are set correctly
CGRect mainBounds = [UIScreen mainScreen].bounds;
if( UIInterfaceOrientationIsLandscape(interfaceOrientation) )
{
int width = mainBounds.size.width;
int height = mainBounds.size.height;
mainBounds.size.width = height;
mainBounds.size.height = width;
}
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
// for iPhone the aspect ratio does not fit, so let's correct it
if( UIInterfaceOrientationIsLandscape(interfaceOrientation) )
{
mainBounds.size.height = 360; // because our renderer is a bit larger
mainBounds.origin.y = -20;
}
else
{
mainBounds.size.width = 360; // because our renderer is a bit larger
mainBounds.origin.x = -20;
}
}
self.glView.frame = mainBounds;
}

Window subview not rotating after orientation of the device changes

I'm creating an UIView with a label inside AppDelegate and displaying it like this:
[window addSubview:self.roundedCornerView];
Problem is when I rotate the device the view with label don't rotate at all. The text in the label is in wrong orientation as well. Window in my application got another subview which is the UIViewControllers subview and it is rotating fine.
Do I need to create another UIViewController in my AppDelegate and attach created view to it, then subclassing it and allowing for interface orientation in order to get roundedCornerView to rotate?
UPDATE
Ok I've tried to do this by creating new ViewController and sublcassing it here is code in my AppDelegate:
ActivityIndicatorWithLabelViewController *aiWithLabel = [[[ActivityIndicatorWithLabelViewController alloc] init] autorelease];
aiWithLabel.textOfTheLabel = text;
[window addSubview:aiWithLabel.view];
The ActivityIndicatorWithLabelViewController class is visible here:
//
// ActivityIndicatorWithLabelViewController.m
// LOFT
//
// Created by Marcin Zyga on 15.11.2011.
// Copyright (c) 2011 __MyCompanyName__. All rights reserved.
//
#import "ActivityIndicatorWithLabelViewController.h"
#implementation ActivityIndicatorWithLabelViewController
#synthesize roundedCornerView;
#synthesize textActivityIndicatorLabel;
#synthesize textOfTheLabel;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
}
*/
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
UIActivityIndicatorView *mainApplicationActivityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
mainApplicationActivityIndicatorView.frame = CGRectMake(80, 80, 40, 40);
mainApplicationActivityIndicatorView.hidesWhenStopped = YES;
//self.roundedCornerView = [[[UIView alloc] initWithFrame:CGRectMake(280, 400, 200, 200)] autorelease];
self.roundedCornerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)] autorelease];
roundedCornerView.backgroundColor = [UIColor blackColor];
roundedCornerView.alpha = 0.9f;
roundedCornerView.layer.cornerRadius = 12.0;
[roundedCornerView addSubview:mainApplicationActivityIndicatorView];
[mainApplicationActivityIndicatorView startAnimating];
// self.roundedCornerView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
//self.roundedCornerView.autoresizesSubviews = YES;
self.textActivityIndicatorLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 150, 200, 50)];
self.textActivityIndicatorLabel.backgroundColor = [UIColor clearColor];
self.textActivityIndicatorLabel.textAlignment = UITextAlignmentCenter;
self.textActivityIndicatorLabel.textColor = [UIColor whiteColor];
self.textActivityIndicatorLabel.font = [UIFont systemFontOfSize:22];
self.textActivityIndicatorLabel.text = #"";
// self.textActivityIndicatorLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
[self.roundedCornerView addSubview:textActivityIndicatorLabel];
self.textActivityIndicatorLabel.text = textOfTheLabel;
self.view.frame = CGRectMake(280, 400, 200, 200);
[self.view addSubview:self.roundedCornerView];
//self.view = self.roundedCornerView;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
[self.textActivityIndicatorLabel removeFromSuperview];
[self.textActivityIndicatorLabel release];
self.textActivityIndicatorLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
self.textActivityIndicatorLabel.backgroundColor = [UIColor clearColor];
self.textActivityIndicatorLabel.textAlignment = UITextAlignmentCenter;
self.textActivityIndicatorLabel.textColor = [UIColor whiteColor];
self.textActivityIndicatorLabel.font = [UIFont systemFontOfSize:22];
self.textActivityIndicatorLabel.text = #"Landscape";
[self.roundedCornerView addSubview:textActivityIndicatorLabel];
NSLog(#"LANDSCAPE");
}
NSLog(#"ENTERING SUPPORTED ORIENTATION!");
return YES;
}
#end
As you see there is some debug code in here. When I'm rotating the device from potrait to landscape I get ENTERING SUPPORTE ORIENTATION! as well as LADNSCAPE NSLog. Removing label is working fine, but when I'm adding new one it is still presented (the text) in wrong orientation. What I am doing wrong?
UIWindow should only have one subview which defines the root UIViewController. I believe that UIWindow only forwards rotation events to its first subview.
Create a single container UIView and move your subviews into it.
Solution is follow below steps :
In subView's .m file add code on top of interface of you view:
typedef NS_OPTIONS(NSUInteger, AGInterfaceOrientationMask) {
AGInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
AGInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
AGInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
AGInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
AGInterfaceOrientationMaskLandscape = (AGInterfaceOrientationMaskLandscapeLeft | AGInterfaceOrientationMaskLandscapeRight),
AGInterfaceOrientationMaskAll = (AGInterfaceOrientationMaskPortrait | AGInterfaceOrientationMaskLandscapeLeft | AGInterfaceOrientationMaskLandscapeRight | AGInterfaceOrientationMaskPortraitUpsideDown),
AGInterfaceOrientationMaskAllButUpsideDown = (AGInterfaceOrientationMaskPortrait | AGInterfaceOrientationMaskLandscapeLeft | AGInterfaceOrientationMaskLandscapeRight),
}
In subView's .m file add code
#pragma mark - Orientation
- (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 orientation = [self desiredOrientation];
CGFloat angle = [self UIInterfaceOrientationAngleOfOrientation:orientation];
CGFloat statusBarHeight = [[self class] getStatusBarHeight];
UIInterfaceOrientation statusBarOrientation = [UIApplication sharedApplication].statusBarOrientation;
CGAffineTransform transform = CGAffineTransformMakeRotation(angle);
CGRect frame = [[self class] rectInWindowBounds:self.view.window.bounds statusBarOrientation:statusBarOrientation statusBarHeight:statusBarHeight];
[self setIfNotEqualTransform:transform frame:frame];
CGRect rect = btnClose.frame;
rect.origin.x = (subView.frame.origin.x+subView.frame.size.width)-(rect.size.width/2);
rect.origin.y = subView.frame.origin.y-(rect.size.height/2);
btnClose.frame = rect;
}
- (void)setIfNotEqualTransform:(CGAffineTransform)transform frame:(CGRect)frame
{
if(!CGAffineTransformEqualToTransform(self.view.transform, transform))
{
self.view.transform = transform;
}
if(!CGRectEqualToRect(self.view.frame, frame))
{
self.view.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;
}
}
static BOOL IS_BELOW_IOS_7()
{
static BOOL answer;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
answer = [[[UIDevice currentDevice] systemVersion] floatValue] < 7.0;
});
return answer;
}
+ (CGRect)rectInWindowBounds:(CGRect)windowBounds statusBarOrientation:(UIInterfaceOrientation)statusBarOrientation statusBarHeight:(CGFloat)statusBarHeight
{
CGRect frame = windowBounds;
if(IS_BELOW_IOS_7())
{
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;
}
- (UIInterfaceOrientation)desiredOrientation
{
UIInterfaceOrientation statusBarOrientation = [[UIApplication sharedApplication] statusBarOrientation];
AGInterfaceOrientationMask statusBarOrientationAsMask = [self AGInterfaceOrientationMaskFromOrientation:statusBarOrientation];
if(self.supportedInterfaceOrientations & statusBarOrientationAsMask)
{
return statusBarOrientation;
}
else
{
if(self.supportedInterfaceOrientations & AGInterfaceOrientationMaskPortrait)
{
return UIInterfaceOrientationPortrait;
}
else if(self.supportedInterfaceOrientations & AGInterfaceOrientationMaskLandscapeLeft)
{
return UIInterfaceOrientationLandscapeLeft;
}
else if(self.supportedInterfaceOrientations & AGInterfaceOrientationMaskLandscapeRight)
{
return UIInterfaceOrientationLandscapeRight;
}
else
{
return UIInterfaceOrientationPortraitUpsideDown;
}
}
}
-(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;
}
-(AGInterfaceOrientationMask)AGInterfaceOrientationMaskFromOrientation:(UIInterfaceOrientation)orientation
{
return 1 << orientation;
}
//If dealloc is a duplicate method then remove this dealloc method and add the unregisterFromNotifications method in dealloc.
- (void)dealloc {
[self unregisterFromNotifications];
}
-(void)unregisterFromNotifications
{
//for orientation
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidChangeStatusBarFrameNotification object:nil];
}
Also In subView's .h file add this line.
- (void)rotateAccordingToStatusBarOrientationAndSupportedOrientations;
Now time to use above added code for orientation change in subview.
While adding subview in window or self.view like this :
[objAppDelegate.window addSubview:objViewController.view];
//added this method to rotate subview according to orientation when added
[objViewController rotateAccordingToStatusBarOrientationAndSupportedOrientations];
Reference taken from AGWindowView
Window subviews don't rotate by themselves, they usually rotate with the help of a view controller.
You could either add the views you want rotated to a view controller and then add that to the window, or you could register for device orientation changes notifications and rotate them yourself.

ViewController orientation change

I'm pushing a ViewController when the iPhone changes orientation to landscape and I'm having trouble with changing the orientation of the ViewController.
I used that code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
Storage *strg = [Storage sharedStorage];
if ([strg.orient intValue] == 2)
{
[[UIApplication sharedApplication] setStatusBarOrientation:
UIInterfaceOrientationLandscapeRight];
UIScreen *screen = [UIScreen mainScreen];
CGFloat screenWidth = screen.bounds.size.width;
CGFloat screenHeight = screen.bounds.size.height;
UIView *navView = [[self navigationController] view];
navView.bounds = CGRectMake(0, 0, screenHeight, screenWidth);
navView.transform = CGAffineTransformIdentity;
navView.transform = CGAffineTransformMakeRotation(1.57079633);
navView.center = CGPointMake(screenWidth/2.0, screenHeight/2.0);
[UIView commitAnimations];
}
if ([strg.orient intValue] == 1)
{
[[UIApplication sharedApplication] setStatusBarOrientation:
UIInterfaceOrientationLandscapeLeft];
UIScreen *screen = [UIScreen mainScreen];
CGFloat screenWidth = screen.bounds.size.width;
CGFloat screenHeight = screen.bounds.size.height;
UIView *navView = [[self navigationController] view];
navView.bounds = CGRectMake(0, 0, screenHeight, screenWidth);
navView.transform = CGAffineTransformIdentity;
navView.transform = CGAffineTransformMakeRotation(4.71238898);
navView.center = CGPointMake(screenWidth/2.0, screenHeight/2.0);
[UIView commitAnimations];
}
}
The result is not consistent; sometimes it goes into the right orientation and sometimes it's upside-down.
When I go from LandcapeRight to LandscapeLeft strait away (and vise versa) it works fine, the problem is only when I go to portrait mode.
Any ideas what I'm doing wrong?
If you really are responding to device orientation change they you probably shouldn't be using setStatusBarOrientation. I think you'd be better off making your viewcontrollers rotate to the supported orientations using shouldAutorotateToInterfaceOrientation and deviceDidRotateSelector notifications.
[[NSNotificationCenter defaultCenter] addObserver: self selector: #selector(deviceDidRotateSelector:) name: UIDeviceOrientationDidChangeNotification object: nil];
-(void)deviceDidRotateSelector:(NSNotification*) notification {
// respond to rotation here
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
//Return YES for supported orientations
return YES;
}

How to set the different image view frame size in Orientations in iPhone?

I have created the the image view and set the images in that view and added the image view as sub view of the scroll view(like slide show images). SO i want to set the image view frame size and scroll view frame size as dynamically. I want to set the different image view frame size and the scroll view size in the portrait and landscape mode. So how can i set the different frame size in the landscape and portrait mode.
Here my sample code,
- (void)viewDidLoad {
[super viewDidLoad];
self.scroll = [[UIScrollView alloc] init];
self.scroll.delegate = self;
self.scroll.pagingEnabled = YES;
self.scroll.contentMode = UIViewContentModeScaleAspectFit;
self.scroll.autoresizingMask = ( UIViewAutoresizingFlexibleHeight |
UIViewAutoresizingFlexibleWidth );
[self.view addSubview:self.scroll];
totalArray = [[NSMutableArray alloc] initWithObjects:[UIImage imageNamed:#"dashboard_demo_2.png"],
[UIImage imageNamed:#"dashboard_demo_1.png"],
[UIImage imageNamed:#"dashboard_demo_2.png"],
[UIImage imageNamed:#"3.jpg"],
[UIImage imageNamed:#"4.jpg"],
[UIImage imageNamed:#"12.jpg"],
[UIImage imageNamed:#"5.jpg"],nil];
x = 0;
for(int i = 0; i< [totalArray count]; i++)
{
img = [[UIImageView alloc] initWithFrame:CGRectMake(x, 0, 320, 200)];
img.image =[totalArray objectAtIndex:i];
x = x+320; // in portait mode if the image sets correctly, but landscape mode it will x = x + 480;
[self.scroll addSubview:img];
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (orientation == UIDeviceOrientationPortrait ||
orientation == UIDeviceOrientationPortraitUpsideDown )
{
[self portraitMode];
}
else if (orientation == UIDeviceOrientationLandscapeLeft ||
orientation == UIDeviceOrientationLandscapeRight )
{
[self LandscapeMode];
}
return YES;
}
-(void) portraitMode
{
//How to set the frame sizes.
self.scroll.frame = CGRectMake(0, 0, 320, 200);
img.frame = CGRectMake(x, 0, 320, 200);
scroll.contentSize = CGSizeMake(x, 200); // it doesn't set
}
-(void) LandscapeMode
{
//How to set the frame sizes
self.scroll.frame = CGRectMake(0, 0, 480, 320);
img.frame = CGRectMake(x, 0, 480, 200);
scroll.contentSize = CGSizeMake(x, 320); // it doesn't set
}
PLease help me out.
Thanks.
Hi ,
you can register to notification center for change in screen orientation.
Code to enroll with notification center.
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(ScreenRotate:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
Implement the ScreenRotate method.
-(void) screenRotate:(NSNotificationCenter*) notification
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if( orientation == UIDeviceOrientationLandscapeLeft)
{
}
else if ( orientation == UIDeviceOrientationLandscapeRight )
{
}
else if ( orientation == UIDeviceOrientationPortrait )
{
}
}
Code to unregister with notification center.
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIDeviceOrientationDidChangeNotification
object:nil];
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}