Manually Rotating UIViews Instead of Autorotation - ios

In iOS, what is the proper way to manually rotate your views? I have a lot of custom rotation animations and I don't want my view to autorotate at all.
Right now, I'm doing this...
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return interfaceOrientation == UIDeviceOrientationPortrait;
}
Then, I'm doing this and responding to orientation changes as needed:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
Everything is working fine, except... When I try to present action sheets, a MailViewController, etc, they all display in portrait orientation :(
How can I have my view know that, while I don't want it to autorotate, it is in fact responding to orientation notifications which I am handling manually?
Edit: To clarify, it's not that my rotations aren't working, it's that when I present a UIActionSheet, it assumes I must be in portrait (even when I've manually rotated so that I'm not), and it displays incorrectly.

Try to use [[UIApplication sharedApplication] setStatusBarOrientation:(UIInterfaceOrientation)]; when you manualy rotate your view

Maybe you can call a method from within shouldAutorotateToInterfaceOrientation.
for example:
- (BOOL)shouldAutorotateToInterfaceOrientation (UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation != UIDeviceOrientationPortrait)
[self theActionYouWantToPerform]
// Return YES for supported orientations
return interfaceOrientation == UIDeviceOrientationPortrait;
}

The line reported by Anton K
[[UIApplication sharedApplication] setStatusBarOrientation:(UIInterfaceOrientation)];
Works me fine!. Is IT just the element that rested me when I want to MANUALLY rotate an UIView of an UIViewController using the CGAFFineTransformMakeRotation method for rotating the view PI/2 radians.
This line, set the ORIENTATION of the STATUS BAR to the (UIInterfaceOrientation) you want, for making the perfect appearance of an UIView "manually" rotated to the (UIInterfaceOrientation) I want.
In consequence, this line also makes UIMessageView's further presented, appears it in the (UIInterfaceOrientation) you indicated.

Related

Force UiInterfaceOrientation from Landscape to Portrait?

I know may be it's a duplicate question, but I tried many answers described here and I can't get it working from hours.
I'm working on an application for IOS 6 and IOS 7, just I need to move from my first viewController "A" which is on Landscape orientation, to a second viewController "B" which is on Portrait orientation.
I configured the project to enable all desired orientation, set the "appropriate" code, but still get the second view displayed vertically on a landscape orientation..
here is the code I set for first controller :
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape ;
}
Plz help.
If you use the UINavigationViewController methods(pushViewController:animated: and popViewControllerAnimated:), the views will inherit the previous view's orientation.
On the other hand, if you use presentModalViewController:animated: and dismissModalViewControllerAnimated: methods, everything works perfectly.
Also here is a sample project which is also changing orientation as required by you

Status bar is not changing it's orientation

Hi I'm using the following code to rotate the orientation of the screen programmatically, without rotating the real device.
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortraitUpsideDown animated:NO];
It rotates everything except the status bar. Can you please tell me, how can I rotate everything on the screen programmatically?
Implement this in your viewController
- (BOOL)shouldAutorotate {
return NO;
}
Your root view controller required to answer NO to shouldAutorotate for your app to respond setStatusBarOrientation:animated method.

shouldAutorotate is not locking the screen orientation

I ma trying to lock screen orientation to only landscape orientation when a certain image is still visible, then when the image is hidden, unlock all orientations (targeting iOS 6):
-(BOOL)shouldAutorotate{
if (self.splashImageView.hidden == NO) {
return UIInterfaceOrientationMaskPortrait;//gets called when image is visible
}else{
return UIInterfaceOrientationMaskAll;//gets called when image is hidden
}
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[self shouldAutorotate];
}
As you may notice, shouldAutorotate is called properly but the screen is always supporting landscape orientation even when the image is still visible, is there something missing?
P.S: Please note I am trying to get that to work on a tabbar view controller (a UIViewController subclass).
In your appdelegate you have those two methods.but do you have setting like in your project settings -> go to summary tab and see if orientation is set to only landscape or all.Just try to set those.

Set keyboard orientation only (iOS 6)

my app has been working fine until I've tried making some changes using the ios 6 SDK
The app runs in portrait mode 99% of the time. This has been constrained by only allowing portait mode to be available in the info.plist
There is one view controller which needs to be shown in landscape mode. This is achieved "manually" by simply rotating the view by 90 degrees, like so:
self.view.transform = CGAffineTransformMakeRotation(3.14159/2);
This still works fine in iOS 6.
However, this view controller has some text fields. When the user taps one it shows the keyboard. Since I've only rotated the view (and not actually changed the orientation of the device), the keyboard comes out in portrait mode, which is no good.
In previous versions of iOS, I set the orientation of the status bar to be landscape, and as a byproduct, this would set the keyboard to be landscape as well, like this:
[[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeRight animated:NO];
However, this has stopped working for iOS 6.
I have read a million stack overflows trying to get this to work, but still have no luck.
Changing the keyboard orientation and transform is an difficult part and not a good solution(especially when it changes status bar orientations).
Better solutions is to allow application to support all orientations.
Implement the Orientation delegates inside your ViewControllers asper the rotation support.
For Supporting only Landscape
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return interfaceOrientation == UIInterfaceOrientationLandscapeLeft
|| interfaceOrientation == UIInterfaceOrientationLandscapeRight ;
}
- (BOOL)shouldAutorotate
{
return NO;
}
For Supporting only Portrait
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (BOOL)shouldAutorotate
{
return NO;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}

How do I notify system when supportedInterfaceOrientations changes?

My root view controller's implementation of supportedInterfaceOrientations almost always returns UIInterfaceOrientationMaskAll, however there is one edge case where it returns UIInterfaceOrientationMaskLandscape.
This is working, if the user rotates the device. However if the device is being held in portrait mode the supportedInterfaceOrientations method does not ever get called, unless the user manually rotates the device.
How can I programatically tell the system that the return value of this method has changed?
According to the documentation, it seems like I should be able to call [UIViewController attemptRotationToDeviceOrientation] however this does not have any effect (supportedInterfaceOrientations is never called and the screen does not rotate).
I found various workarounds others have posted to try and solve this problem, but none of them work in my tests. I suspect they may have worked in iOS 5.0, but not iOS 6.0.
I am returning YES in the root view controller's shouldAutorotate method.
First of all, it might be useful if you used this if you want to present your UIViewController in Landscape mode.
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft | UIInterfaceOrientationLandscapeRight;
}
Also, A lot depends on with which controller is your UIViewController embedded in.
Eg, If its inside UINavigationController, then you might need to subclass that UINavigationController to override orientation methods like this.
subclassed UINavigationController (the top viewcontroller of the hierarchy will take control of the orientation.) needs to be set it as self.window.rootViewController.
- (BOOL)shouldAutorotate
{
return self.topViewController.shouldAutorotate;
}
- (NSUInteger)supportedInterfaceOrientations
{
return self.topViewController.supportedInterfaceOrientations;
}
From iOS 6, it is given that UINavigationController won't ask its UIVIewControllers for orientation support. Hence we would need to subclass it.
Note :
The shouldAutorotate and supportedInterfaceOrientations method always get called for UINavigationController whenever Push operations are done.
Quote from Apple's UIViewController Class Reference:
Note: At launch time, apps should always set up their interface in a portrait orientation. After the application:didFinishLaunchingWithOptions: method returns, the app uses the view controller rotation mechanism described above to rotate the views to the appropriate orientation prior to showing the window.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html
If the interface starts in portrait the autorotation should be able to handle the adjustment even if the user opens the app with the device on its side.
Update: I found this post that should help with rotations after launch. Apparently iOS 6 looks at the navigation controller to determine supported device orientations.
How to force a UIViewController to Portrait orientation in iOS 6
You need to manually rotate it. You'll want to call the following logic in your view controller's viewWillAppear: method:
UIDeviceOrientation curDevOrientation = [[UIDevice currentDevice] orientation];
if (![self supportsOrientation:curDevOrientation]) {
// We're going to rotate 90 degrees clockwise. First figure out what that
// means to the status bar.
UIInterfaceOrientation newStatusBarOrientation;
switch (curDevOrientation) {
case UIDeviceOrientationPortrait:
newStatusBarOrientation = UIInterfaceOrientationLandscapeRight;
break;
case UIDeviceOrientationPortraitUpsideDown:
newStatusBarOrientation = UIInterfaceOrientationLandscapeLeft;
break;
}
[[UIApplication sharedApplication] setStatusBarOrientation:newStatusBarOrientation animated:NO];
// Now rotate the view 90 degrees clockwise.
CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI * 90.0 / 180.0);
self.view.transform = transform;
}
That should rotate the particular view controller's view, whenever it appears.

Resources