How to manage application when orientation changes? - iphone

I have an application in which I am changing screen orientation. But when I change orientation for the first screen and go to the next screen, the change does not persist.
Attached are images for clearer understanding.
The main problem is that when device is rotated then first screen rotates but second does not launch in the new orientation.
It will rotate only when we change orientation after the screen is launched.
How do I fix that?

The problem is that when you rotate the device then
(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
Method gets called but when you go to the next screen then this method does not get called. if you rotate your device again then that method gets called.
So if you want to change next screen orientation as device current orientation, then check the device's current orientation with viewDidLoad method or ViewWillApper() method. Then according to that set your current view.

Use this buddy...
If suppose, you are adding UIImageView to your self.view as
**in .h**,
UIImageView *topView
**in .m**,
topView = [[UIImageView alloc] initWithImage:
[UIImage imageNamed:#“anyImage.png"]];
topView.userInteractionEnabled = YES;
UIInterfaceOrientation interfaceOrientation = [UIApplication sharedApplication].statusBarOrientation;
if(interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
topView.frame = // set your dimensions as per landscape view
}
else if(interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
topView.frame = // set your dimensions as per portrait view
}
[self.view addSubView : topView];
**Add this lines at end of your viewDidLoad.**
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didRotate:)
name:#"UIDeviceOrientationDidChangeNotification"
object:nil];
**And the method**
- (void)didRotate:(NSNotification *)notification
{
UIDeviceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
CGRect screenBounds = [[UIScreen mainScreen] bounds];
switch (orientation)
{
case UIInterfaceOrientationLandscapeLeft:
{
topView.frame = // set your dimensions as per landscape view
break;
}
case UIInterfaceOrientationLandscapeRight:
{
topView.frame = // set your dimensions as per landscape view
break;
}
case UIInterfaceOrientationPortraitUpsideDown:
{
topView.frame = // set your dimensions as per portrait view
break;
}
case UIInterfaceOrientationPortrait:
{
topView.frame = // set your dimensions as per portrait view
break;
}
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
Happy coding..

call this method.
-(void) viewWillAppear:(BOOL)animated{
UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation];
[self willAnimateRotationToInterfaceOrientation:orientation duration:0];
}
-(void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if(toInterfaceOrientation == UIInterfaceOrientationPortrait || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown )
{
enter code here
set frame.........
}
else if(toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight )
{
set frame.........
}
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return YES;
}

Related

how to rotate parent view controller when child view controller orientation changes in iOS

I am displaying Child view controller on my parent view controller using
childView1 *viewController = [[childView1 alloc]initWithNibName:examTFVC_NIB bundle:nil row:gesture.view.tag productID:test_productID size:testsize Duration:duration];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
self.view.alpha = 0.4f;
viewController.view.backgroundColor = [UIColor clearColor];
viewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:viewController animated:YES completion:NULL];
I am displaying transparent view controller over my parent view controller and its landscape only.
but issue is when i change the device from landscape left to landscape right or right to left than my child view controller orientation changes but parent view controller remain same orientation.
My parent view controller orientation changes when i am not displaying child view controller how can i change parent view controller orientation along with child?
One thing i tried to change orientation by programming passing Notification Center from child to parent to change the orientation.
In child view controller
- (NSUInteger)supportedInterfaceOrientations
{
NSUInteger supportedOrientations = UIInterfaceOrientationMaskLandscape;
[[NSNotificationCenter defaultCenter] postNotificationName:#"RotateParent"object:nil];
return supportedOrientations;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight );
}
- (BOOL)shouldAutorotate
{
return YES;
}
In parent view controller
-(void)rotateParent:(NSNotification *)notification
{
CGAffineTransform transform = CGAffineTransformMakeRotation(-M_PI);
self.view.transform = transform;
NSLog(#"Parent rotate ");
}
but when i click to display my child over parent view than my "rotateParent" method get executed one time by default.
any other solution??
For < iOS 6.0
in childView1
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
[[NSNotificationCenter defaultCenter] postNotificationName:#"RotateParent"object:nil];
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||interfaceOrientation == UIInterfaceOrientationLandscapeRight );
}
For > iOS 6.0
- (BOOL)shouldAutorotate
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"RotateParent" object:nil];
return YES;
}
in Parent View
Add observer for notification, and based on current orientation rotate parent view with proper angle.
-(void)rotateParent:(NSNotification *)note{
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
CGFloat rotationAngle = 0;
if (orientation == UIDeviceOrientationPortraitUpsideDown) rotationAngle = M_PI;
else if (orientation == UIDeviceOrientationLandscapeLeft) rotationAngle = M_PI_2;
else if (orientation == UIDeviceOrientationLandscapeRight) rotationAngle = -M_PI_2;
[UIView animateWithDuration:0.5 animations:^{
self.view.transform = CGAffineTransformMakeRotation(rotationAngle);
self.view.transform = CGAffineTransformMakeRotation(rotationAngle);
self.view.transform = CGAffineTransformMakeRotation(rotationAngle);
} completion:nil];
//adjust view frame based on screen size
if(orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
self.view.bounds = CGRectMake(0.0, 0.0, 480, 320);
}
else
{
self.view.bounds = CGRectMake(0.0, 0.0, 320, 480);
}
}
let me know if you face any issue.
Hey if I have understood your problem correctly, than you may want to look into this superb method from UIView.
- (void)viewWillLayoutSubviews
When a view’s bounds change, the view adjusts the position of its
subviews. Your view controller can override this method to make
changes before the view lays out its subviews. The default
implementation of this method does nothing.
So this method will get called before every subsequent rotation of your Child View Controller and you can post notification to your parent view controller from this method.

iPhone orientation issue in single class

i have 4 classes (class1, class2, class3 & class4) for class1, class2 & class3 i have all modes support (Landscape & Portrait). But for class 4 i need only Portrait support. Issue here is when i load class4 in Landscape mode its showing view in landscape, when i rotate class4 to Portrait mode once, its not rotating to landscape again. I want class4 to load in portrait only weather i come load class 4 in portrait or landscape mode.
i tried this
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation != UIInterfaceOrientationPortrait)
{
return NO;
}
}
Please let me know, how to proceed
Seems like all you need to do is return a YES for everything but portrait orientation.
How about:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// b.t.w., there is also an upside down portrait constant
// which is UIInterfaceOrientationPortraitUpsideDown
if (interfaceOrientation != UIInterfaceOrientationPortrait)
{
return NO;
}
return YES;
}
B.T.W., according to the public documentation for shouldAutorotateToInterfaceOrientation:, this API is deprecated as of iOS 6.0. If you care about your app's survivability for the future, you may want to consider doing something different.
Try this
-(void)orientationChanged:(NSNotification *)object{
NSLog(#"orientation change");
UIDeviceOrientation deviceOrientation = [[object object] orientation];
if(deviceOrientation == UIInterfaceOrientationLandscapeLeft ||deviceOrientation == UIInterfaceOrientationLandscapeRight)
{
Bg.image=[UIImage imageNamed:#"splashBgL.png"]; ///Lendscape Background
Bg.frame=CGRectMake(0, 0, 480, 320);
self.view.frame=CGRectMake(0, 0, 480, 320);
}
else{
Bg.image=[UIImage imageNamed:#"splashBg.png"];///Protrait Background
Bg.frame=CGRectMake(0, 0, 320, 480);
}
}
-(void)landscapeLeftOrientation{
CGRect contentRect = CGRectMake(0, 0, 480, 320);;
self.view.bounds = contentRect;
}
-(void)landscapeRightOrientation{
CGRect contentRect = CGRectMake(0, 0, 480, 320);
self.view.bounds = contentRect;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:)name:#"UIDeviceOrientationDidChangeNotification" object:nil];
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self landscapeLeftOrientation];
}

Device rotaion issue

I detect screen change orientation with :
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(detectOrientation) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
and when it call i call this method:
if(orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
[md changeToBigNowPlaying:YES withLayer:avPlayerLayer];
}else{
[md changeToBigNowPlaying:NO withLayer:avPlayerLayer];
}
and in this function i do this stuff:
-(void)changeToBigNowPlaying:(BOOL)flag withLayer:(AVPlayerLayer*)layer{
if (flag) {
//To portrait
[landVC.view removeFromSuperview];
[layer removeFromSuperlayer];
[self.window addSubview:tab.view];
}else {
//To landscape
[tab.view removeFromSuperview];
[landVC setUpNewLayer:layer];
[self.window addSubview:landVC.view];
}
}
and this is the explanation :
I have tabbar with viewcontroller,and when i detect that the user rotate the screen to landscape i remove the tabbar and add a UIViewController(landVC) and when i rotate it to portrait again i remove the landvc and add again the tabbar.
my problem is when i rotate first to UIInterfaceOrientationLandscapeLeft so it show me the screen in UIInterfaceOrientationLandscapeRight. but when i rotate to UIInterfaceOrientationLandscapeRight first i see the screen like it should and when i rotate from this situation to UIInterfaceOrientationLandscapeLeft i see the screen good too.
any idea why i have a problem when i rotate to UIInterfaceOrientationLandscapeLeft and i see the landVc in UIInterfaceOrientationLandscapeRight
In landVC UIViewController i implement:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
if(interfaceOrientation == UIInterfaceOrientationLandscapeRight){
return YES;
}else if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
return YES;
}else {
return NO;
}
}
Edit
-(void)detectOrientation{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if(orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {
[md changeToBigNowPlaying:YES withLayer:avPlayerLayer];
}
if(orientation == UIInterfaceOrientationLandscapeRight || orientation == UIInterfaceOrientationLandscapeLeft) {
[md changeToBigNowPlaying:NO withLayer:avPlayerLayer];
}
}

Labels not aligning properly in landscape mode

Is the code below correct? When the user rotates the device, two labels are supposed to go to the coordinates given below. It works when the user starts the app in portrait mode, the labels are placed correctly. However, when the user starts in landscape mode, the labels DO NOT get placed correctly. But if you rotate the view to portrait and then back to landscape, they align properly. I've tried placing the landscape coordinates in viewDidLoad, and it still doesn't work. What should I do? Thanks for your help!
The two labels are recordingTimeLabel and recordingTimeLabelMinutes.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeRight || toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
//is landscape
backGround.frame = CGRectMake(0, 0, 768, 1024);
recordingTimeLabel.center = CGPointMake(967, 22);
recordingTimeLabelMinutes.center = CGPointMake(901, 22);
NSLog(#"is landscape");
// fixedSpace.width = 400;
} else {
//is portrait
backGround.frame = CGRectMake(0, 0, 1024, 768);
recordingTimeLabel.center = CGPointMake(710, 22);
recordingTimeLabelMinutes.center = CGPointMake(661, 22);
NSLog(#"is portrait");
}
}
Additionally, this code doesn't work either:
-(void)viewWillAppear:(BOOL)animated {
if (([[UIDevice currentDevice] orientation] == UIInterfaceOrientationLandscapeRight) || ([[UIDevice currentDevice] orientation] == UIInterfaceOrientationLandscapeLeft)) {
//is landscape
backGround.frame = CGRectMake(0, 0, 768, 1024);
recordingTimeLabel.center = CGPointMake(967, 22);
recordingTimeLabelMinutes.center = CGPointMake(901, 22);
NSLog(#"is landscape");
} else {
//is portrait
backGround.frame = CGRectMake(0, 0, 1024, 768);
recordingTimeLabel.center = CGPointMake(710, 22);
recordingTimeLabelMinutes.center = CGPointMake(661, 22);
NSLog(#"is portrait");
}
}
willRotateToInterfaceOrientation: may not be called if you start in landscape mode. I suggest setting the coordinates in viewWillAppear:, not viewDidLoad, to figure out the initial orientation (you can use self.interfaceOrientation if you have autorotation enabled).
Have you set following code also for the UIInterfaceOrientation?
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
Got it. I used an NSTimer and called a function very often that contained this code:
-(void)updateLabelLocation {
if (([[UIDevice currentDevice] orientation] == UIInterfaceOrientationLandscapeRight) || ([[UIDevice currentDevice] orientation] == UIInterfaceOrientationLandscapeLeft)) {
recordingTimeLabel.center = CGPointMake(710, 22);
recordingTimeLabelMinutes.center = CGPointMake(661, 22);
}
}

UIViewController autorotate some components?

I have a UIViewController that has an image view and a toolbar. I would like the toolbar to rotate, but the imageview to stay as it is. Is this possible?
Yes this is possible, but requires manual handling of rotate events.
In viewDidLoad, add
// store the current orientation
currentOrientation = UIInterfaceOrientationPortrait;
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector: #selector(receivedRotate:) name: UIDeviceOrientationDidChangeNotification object: nil];
if(currentOrientation != self.interfaceOrientation) {
[self deviceInterfaceOrientationChanged:self.interfaceOrientation];
}
and don't forget to deregister events when the controller is removed.
Then add a method for rotates:
// This method is called by NSNotificationCenter when the device is rotated.
-(void) receivedRotate: (NSNotification*) notification
{
NSLog(#"receivedRotate");
UIDeviceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];
if(interfaceOrientation != UIDeviceOrientationUnknown) {
[self deviceInterfaceOrientationChanged:interfaceOrientation];
} else {
NSLog(#"Unknown device orientation");
}
}
and finally the rotate method
- (void)deviceInterfaceOrientationChanged:(UIInterfaceOrientation)interfaceOrientation {
if(interfaceOrientation == currentOrientation) {
NSLog(#"Do not rotate to current orientation: %i", interfaceOrientation);
} else if(interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
NSLog(#"Do not rotate to UIInterfaceOrientationPortraitUpsideDown");
} else if(interfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
NSLog(#"Do not rotate to UIInterfaceOrientationLandscapeLeft");
} else {
if(!isRotating)
{
isRotating = YES;
if(currentOrientation == UIInterfaceOrientationPortrait && interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
NSLog(#"Rotate to landscape");
// rotate to right top corner
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
// do your rotation here
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDoneShowCaption:finished:context:)];
[UIView commitAnimations];
} else if(currentOrientation == UIInterfaceOrientationLandscapeRight && interfaceOrientation == UIInterfaceOrientationPortrait) {
// etc
}
isRotating = NO;
} else {
NSLog(#"We are already rotating..");
}
}
currentOrientation = interfaceOrientation;
}
Note that I do not allow for rotates in some directions, you might.
In addition, you need to make your components resizable / able to rotate.
Edit Consider using block-based animations instead and set the isRotation = NO in the completion block.