iOS (iPhone/iPad) SDK - Alternative for [[UIApplication sharedApplication] setStatusBarOrientation:animated:] - iphone

Is there an alternative for [[UIApplication sharedApplication] setStatusBarOrientation:animated:]? setStatusBarOrientation, as you can see in it's name, only rotates the status bar. Is there anything that will rotate the whole app like it does when physically rotating the device?

If you want to change the orientation manually (not using autorotation), you will have to rotate and position views yourself, as described in answers to this question. Supporting autorotation is described in the documentation.

if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
if (!window) {
window = [[UIApplication sharedApplication].windows objectAtIndex:0];
}
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelegate:self];
window.transform = CGAffineTransformMakeRotation(-M_PI);
[UIView commitAnimations];
}
Note: you need the coregraphics framework, I guess.

You can indeed force a rotation this way:
if ([[UIDevice currentDevice] respondsToSelector: #selector(setOrientation:)]) {
[[UIDevice currentDevice] setOrientation: UIInterfaceOrientationPortrait];
}
Change UIInterfaceOrientationPortrait to UIInterfaceOrientationLandscape if you wish to rotate to landscape

Related

iPhone set interfaceorientation programmatically

I am trying to change the orientation of a single UIViewController programmatically. The user should choose in the settings if the view will be portrait or not. The value will be saved in NSUserDefaults and in the specific ViewController the orientation should be changed. So if Portrait is on the interfaceOrientation should be on UIInterfaceorientationUpsideDown......
I used following method but it will only change the orientation when the user will turn the device to landscape/portrait... otherwise nothing will be triggered.
- (BOOL)shouldAutoRotateToInterfactOrientation:(UIInterfaceOrientation)interfaceOrientation
Furthermore i tryied the next one (also with method name "setOrientation"):
[[UIDevice currentDevice] orientation: UIDeviceOrientationPortraitUpsideDown];
But again, nothing happens, there just appear errors because xcode sayes there are no methods with this name.
But ther should be another way to change it programatically...
the first method is also just a method that handles the actionListener after device position but there should be a way to call this actionListener in a direct way....
I just looked inside the UIApplication File but there is no usefull method....
You should use something like this code:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(rotationChanged:)
name:#"UIDeviceOrientationDidChangeNotification"
object:nil];
And then, change your view according to the orientation:
-(void)rotationChanged:(NSNotification *)notification{
NSInteger orientation = [[UIDevice currentDevice] orientation];
UIWindow *_window = [[[UIApplication sharedApplication] delegate] window];
switch (orientation) {
case 1:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
[_window setTransform:CGAffineTransformMakeRotation (0)];
[_window setFrame:CGRectMake(0, 0, 320, 480)];
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:YES];
[UIView commitAnimations];
break;
case 2:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
[_window setTransform:CGAffineTransformMakeRotation (M_PI)];
[_window setFrame:CGRectMake(0, 0, 320, 480)];
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:YES];
[UIView commitAnimations];
break;
case 3:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
[_window setTransform:CGAffineTransformMakeRotation (M_PI / 2)];
[_window setFrame:CGRectMake(0, 0, 320, 480)];
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES];
[UIView commitAnimations];
break;
case 4:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
[_window setTransform:CGAffineTransformMakeRotation (- M_PI / 2)];
[_window setFrame:CGRectMake(0, 0, 320, 480)];
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeLeft animated:YES];
[UIView commitAnimations];
break;
default:
break;
}
}
Hope it helps :P
Use this works perfectly on iOS7 and earlier.
[[UIDevice currentDevice] setValue:
[NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
forKey:#"orientation"];
[[UIApplication sharedApplication] setStatusBarOrientation:yourDesiredOrientation];
You will then need to edit the shouldAutoRotate method (following example is for portrait:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
From previous answer:
[[UIDevice currentDevice] setValue:
[NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
forKey:#"orientation"];
WARNING
I haven't a possibility to comment this answer so I'll edit it.
The author of this answer tries to set a value of UIInterfaceOrientation type to a variable of UIDeviceOrientation. They are both NSInteger enums, so compiler will not show a warning/error. But they have different meanings and "device" additionally has "face up" and "face down" orientations.

Placing and Moving Views on Rotation (UIView)

What's the "correct" way of exactly placing and moving views when an app rotates? That is, how can I have fine-grained control of the position, size, and reflow of my views when the UI rotates from portrait to landscape orientation (or vice-versa)? I think my two options are:
Use two superviews (portrait and landscape). On rotation: toggle between them.
Use one superview. On rotation: change each subview's frame, bounds, and center properties.
If you have two views with distinct enough layouts and elements, then the first way might be good enough. If your two views are essentially the same thing sized for different orientations, the second way is probably a better way to do it using only one view.
I suspect the former could be done with IB and the latter should be done programmatically.
To have fine-grained control over the position and size of your subviews when the iPhone rotates, change the frame of the subviews in the UIViewController method willAnimateRotationToInterfaceOrientation:duration:. This method is called within an animation block, so all the changes to your subviews' frames that you make inside of it are animated.
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) {
// Portrait frames
self.subviewA.frame = CGRectMake(x, y, width, height);
self.subviewB.frame = CGRectMake(x, y, width, height);
self.subviewC.frame = CGRectMake(x, y, width, height);
} else {
// Landscape frames
self.subviewA.frame = CGRectMake(x, y, width, height);
self.subviewB.frame = CGRectMake(x, y, width, height);
self.subviewC.frame = CGRectMake(x, y, width, height);
}
}
Here's one idea. I worry that the animations will work funny, but try it and see.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toOrientation
duration:(NSTimeInterval)duration {
if (toOrientation == UIInterfaceOrientationLandscapeLeft ||
toOrientation == UIInterfaceOrientationLandscapeRight) {
[UIView beginAnimations:nil context:NULL]; {
[UIView setAnimationDuration:1.0];
}
[UIView setAnimationDelegate:self];
[viewA setFrame:CGRectMake(?,?,?,?)];
[viewB setFrame:CGRectMake(?,?,?,?)];
[viewC setFrame:CGRectMake(?,?,?,?)];
} [UIView commitAnimations];
} else if (toOrientation == UIInterfaceOrientationPortrait ||
toOrientation == UIInterfaceOrientationPortraitUpsideDown) {
[UIView beginAnimations:nil context:NULL]; {
[UIView setAnimationDuration:1.0];
}
[UIView setAnimationDelegate:self];
[viewA setFrame:CGRectMake(?,?,?,?)];
[viewB setFrame:CGRectMake(?,?,?,?)];
[viewC setFrame:CGRectMake(?,?,?,?)];
} [UIView commitAnimations];
}
I have an idea which is working properly for me where I am using a small view on a view where it rotates itself when orientation of device changes. Use one notifier then in the method change the orientation.
#define DegreesToRadians(x) (M_PI * x / 180.0)
.......
[[NSNotificationCenter defaultCenter] addObserver:showIndicator
selector:#selector(setProperOreintation)
name:UIDeviceOrientationDidChangeNotification
object:nil];
.......
-(void)setProperOrientation {
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
if (orientation == UIDeviceOrientationPortraitUpsideDown)
self.transform = CGAffineTransformRotate(CGAffineTransformIdentity, DegreesToRadians(180));
else if (orientation == UIDeviceOrientationLandscapeLeft)
self.transform = CGAffineTransformRotate(CGAffineTransformIdentity, DegreesToRadians(90));
else if (orientation == UIDeviceOrientationLandscapeRight)
self.transform = CGAffineTransformRotate(CGAffineTransformIdentity, DegreesToRadians(-90));
[UIView commitAnimations]; }
Here instead of rotate u can use translate or scale
There is a lot solutions for that. One of them is animations for controls as you read before. Another option is prepare 2 UIView one for portrait mode and another for landscape mode. And on switch orientation - load proper UIView. That's the way i used in my applications. Because sometimes differences between landscape and portrait is huge.
In simple cases is enough to set up correct autoresizingMask for subviews. Read about it. It works really nice.

Animated status bar style transition, a la iPod app

In the iPod app, the navigation views have the default status bar style, and the Now Playing view is in the black style. The transition between them is animated with a crossfade. I want to do that.
My first attempt:
[UIView beginAnimations:#"whatever" context:nil];
[UIView setAnimationDuration:0.5];
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleBlack
[UIView commitAnimations];
No joy, it pops to black. Takers?
Try this instead:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:YES];

StatusBarHidden not working

Stumped on this one. I am using a section of code posted here to rotate a view into landscape. Rotate, sizing and animations are working great, but when the view rotates, the status bar hangs around as a thin gray strip, which is the same size as the hidden status bar.
Here is the code:
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:1.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];
if (self.interfaceOrientation == UIInterfaceOrientationPortrait) {
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
self.view.bounds = CGRectMake(0.0, 0.0, 480, 320);
}
[UIView commitAnimations];
Thanks in advance!
Did you set wantsFullScreenLayout = YES on your view controller?
iOS7: I added the following code to the Info.plist to get rid of the status bar permanently. Found it in another stackexchange question.
<key>UIStatusBarHidden</key>
<true/>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>

TTThumbView/TTPhotoView no autorotation

In my app I try to use the TTphotoView, so in a ViewController I push the TTphotoView with my navigationController like this:
if(self.photoViewController == nil {
PhotoViewController *viewController = [[PhotoViewController alloc] init];
self.photoViewController = viewController;
viewController.hidesBottomBarWhenPushed = YES;
[viewController release];
}
[self.navigationController pushViewController:self.photoViewController animated:YES];
[self.navigationController  dismissModalViewControllerAnimated:YES]
the problem is when the user rotate the device on the PhotoViewController nothing happen.
EDIT : I can't believe people didn't have the same problem. If someone use the photoView in his application with his own navigation and not the TTNavigation can he tell me how did he push the ViewController?
I had the same problem.
I don't know why but TTScrollView deviceOrientationDidChange method in three20 code is commented out! If you uncomment it, it will work.
See the code here: http://github.com/facebook/three20/blob/master/src/TTScrollView.m
Have you overridden your application's:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
and returned YES for the landscape orientations?
My comment for willcodejavaforfood, as I told you I can force by doing something like for example that but too many problem inside, and the PhotoViewController of three20 must do it by himself so I don't want that:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(receivedRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
-(void) receivedRotate: (NSNotification *) notification {
NSLog(#"ORIENTATION CHANGE");
UIDeviceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];
if(interfaceOrientation == UIDeviceOrientationLandscapeRight) {
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration: 0.5f];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(-M_PI/2);
self.view.bounds = CGRectMake(0.0, 0.0, 480.0, 320.0);
self.view.center = CGPointMake(240.0f, 160.0f);
[UIView commitAnimations];
}
}