Currently, in my app, I need to NOT allow side orientation to occur except for one view that is supposed to show another uiview when the user side-orients. Suppose I have 20 UIViewControllers that are allowed to be accessed from the mainviewcontroller (UINavigationController). Now, also suppose that UIViewController #7, when shown has two views, one that is shown for side orientation and one for portrait orientation.
I don't want you guys to think I want to eliminate Rotation Orientation throughout the app's life but just for 19 of the views, and the last uiviewcontroller have support for it.
If a user does side-orient for that one view, then the user should just see the app as usual with no orientation effects.
I want the user to only use the portrait orientation view and thats it for that one viewcontroller. Maybe if the user rotates the phone 180 degrees, upsidedown, then sure, the app should flip but still be in a portrait view.
ANyone have any ideas? I'm deploying to iOS 6.1 so some methods I have used are deprecated which is what I want to stay away from...
Such as this method:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return NO;
}
I have done several test cases:
- (NSUInteger) supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (BOOL) shouldAutorotate{
return NO;
}
I've also checked up on stackoverflow related questions and I can't simply find an answer.
I figure this should be one maybe two methods I override but I can't do this..... How do I eliminate side orientation in a UIViewController????
There are questions on SO that cover this topic; there's a wealth of information here, for example.
Or, how about this, or this?
IIRC, from one of the WWDC videos I watched on this subject, the recommended way was to do a modal presentation, but there are various hacks at your disposal if you're so inclined.
Edit:
More data here: iOS6 Preferred Interface Orientation Not Working
And here: In iOS6, trouble forcing ViewController to certain interfaceOrientation when pushed on stack
As I said, I believe presenting the view controller (modally or whatnot) is the way to go if you want to force an orientation, see this explanation.
Related
i am currently developing an ios app that uses PayPal's Mobile Payment Library to facilitate payment of goods.The Problem is that Paypal generates a web view that set to portrait -Upright mode. This is to my knowledge is generated inside the payPal library and i can't see anyway to acces it . Is there anyway to make te web view rotate in landscape mode.After some extensive searching i found that most everyone are just using the portait mode ,is there anyway to make it rotate to landscape.
Actually there is a way to manually rotate the checkbox view of paypal in iOS. This view is an instance of PayPalViewClass. Just add a method to look through all the views and all the subviews to find the instanse of this class. Once you've found the view you was looking for just apply setTransform method to it.
The method should look like like this:
-(void)cicle:(UIView *)aView {
for (UIView *_v in [aView subviews]) {
if ([_v isKindOfClass:[NSClassFromString(#"PayPalViewClass") class]]) {
[aView setTransform:CGAffineTransformMakeRotation(-M_PI/2)];
}
[self cicle:_v];
}
}
It should be called in your payWithPayPal method.
I hope this helps ;)
I am having the same problem.
Since PayPal is adding its view to the key window and not the root view controller, then it ignores the device orientation.
There are many questions here that explain the landscape orientation issue, when adding a subview directly to a window, for example:
UIInterfaceOrientation always return Portrait in AppDelegate iPad?
I am trying to catch PayPal UIView and rotate it manually, but not figured out if it is possible yet.
For Paypal library v1.6.0, the PayPalViewClass is in view hierarchy of application's main window.
You just need to call method provided by #alex and pass your app's delegate window.
To get the window [[[UIApplication sharedApplication] delegate] window] is enough.
Put the call after you call -advancedCheckoutWithPayment: or -checkoutWithPayment:.
If you allow all orientations, you will need to transform the PayPalViewClass accordingly to device orientation.
I'm working on an iphone app with a TabBarController as rootcontroller. And this rootcontroller is associated to Navigation Controllers (each one related to a specific Tab Bar button).
One on these navigation controllers shows some photos and thus I needed to enable Lanscape which obviously did not work until I added this code to all view controllers
- (BOOL)shouldAutorotateToInterfaceOrientation (UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}
However, now that all orientations are enabled in all views some views I didn't want in landscape are showing very ugly :(
Any idea how to just leave the landscape orienation only on this photo view and disable it on all other views?
Consider showing the UIViewController that needs full reorientation capabilities modally.
That would be the common and in my humble opinion correct way to handle such situation.
To answer your subject in short: yes, it does have to return YES if you want any of the tabbed viewControllers to allow reorientation. The same goes for viewControllers within the stack of your UINavigationControllers. Hence the same goes for any combination of those.
From Apple's Technical Note on that subject:
Why won't my UIViewController rotate with the device?
All child view controllers in your UITabBarController or
UINavigationController do not agree on a common orientation set. To
make sure that all your child view controllers rotate correctly, you
must implement shouldAutorotateToInterfaceOrientation for each view
controller representing each tab or navigation level. Each must agree
on the same orientation for that rotate to occur. That is, they all
should return YES for the same orientation positions.
In case using a modally presented view controller is no option for you - here comes another way...
There is also a solution possible that seems a little "hacky" but worked for me in the past. I will draft it in a very very "hacky" way to simplify the answer.
Within the shouldAutorotateToInterfaceOrientation:toInterfaceOrientation implementation of all of your viewControllers, return a global value. Change that global value according to the needs of the currently displayed viewController. Even though it is said that a viewController is only asked once, this common rumor has proven untrue for my. So here comes the super hack;
All view controllers within your navigation stack should implement the shouldAutorotate-method like this:
- (BOOL)shouldAutorotateToInterfaceOrientation (UIInterfaceOrientation)toInterfaceOrientation
{
extern BOOL gSouldAutorotateToAnyOrientationFlag;
if (gShouldAutorotateToAnyOrientationFlag)
{
return YES;
}
return UIInterfaceOrientationIsPortrait(toInterfaceOrientation);
}
Now, somewhere in your app, you should declare and instantiate that global flag - you could place this ugly global flag within your app-delegate implementation, directly below the imports and above the #implementation block:
BOOL gShouldAutorotateToAnyOrientationFlag = NO;
Within all viewControllers that are supposed to be shown in portrait mode only, set that flag towards NO - e.g. within viewWillAppear;
- (void)viewWillAppear:(BOOL)animated
{
extern BOOL gShouldAutorotateToAnyOrientationFlag;
gShouldAutorotateToAnyOrientationFlag = NO;
}
Within the viewController/s that are supposed to be shown in any orientation, set that flag towards YES - again within viewWillAppear;
- (void)viewWillAppear:(BOOL)animated
{
extern BOOL gShouldAutorotateToAnyOrientationFlag;
gShouldAutorotateToAnyOrientationFlag = YES;
}
That way, whenever the entire navigation stack is asked for its orientation capabilities, the proper answer will be given. From my experience, the entire stack is asked, over and over again and answers are not cached, hence my hack worked whenever I needed it. Still, the rumor seems to be widespread that those answers are somehow cached and therefor that rumor might be valid in certain cases - hence I shall not be held responsible if this does not work for you (or even down voted :D )
On the view you only want landscape for:
- (BOOL)shouldAutorotateToInterfaceOrientation (UIInterfaceOrientation)toInterfaceOrientation
{
return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}
You can replace UIInterfaceOrientationIsLandscape with UIInterfaceOrientationIsPortrait if that better suits your needs.
I have a UIViewController instance(viewController1) that I want to lock in landscape mode which I am able to do. On tapping on a button I push another UIViewController(viewController2) which supports both orientations. Now, if user changes the orientation of viewController2 to portrait and goes back to viewController1, viewController1 also changes it's orientation to portrait. How can I avoid that?
Thanks in advance.
Add these methods to the view controllers
(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
Thats for the first
(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES);
}
Thats the second
-(BOOL)shouldAutorotateToInterfaceOrientation:UIInterfaceOrientation)toInterfaceOrientation{
if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) {
return YES;
}
return NO;
}
If those 2 controllers are both implementation of UIViewController both differente classes each other! you can just implement the method shouldAutorotateToInterfaceOrientation, in the first! this should work even when u go back!
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) {
return YES;
}
return NO;}
You say push so I assume both ViewControllers are in a NavigationController. If so I'll have to disappoint you, what you want isn't possible. Your rotation callbacks are working correctly, they respond to a rotation, you can't force it. What's happening is the correct behavior.
Best solution is to prevent the user from going back when you're in the orientation the previous ViewController doesn't support, hide the back button for example.
A while back I've made my own NavigationController (doesn't inherit from the UIViewController but it can do exactly the same) and I've tried to implement what you're trying to do. Before pushing or popping, if the view of the ViewController that was about to be shown didn't support the current orientation, I transformed the view of that ViewController by 90° and force the orientation of the status bar to the new ViewController's supported orientation.
As soon as the push or pop was complete I'd do a small trick to force the rotation of the device. If you remove the view of the rootViewController from the window and re-add it, the responder chain will be forced to go through all rotation callbacks. When that happened I checked if a ViewController's view was transformed and reset that transformation.
It did work, mostly. But it was messy code and it goes against Apple's current policy that the rootViewController should be responsible of handling the orientation. Also in iOS6 forcing the status bar orientation is guaranteed to work. So I'd really advise against doing this, I've removed this from my own NavigationController too.
I have a view in my app that has three segmentedButtonControllers and I designed it with portrait mode. When I rotate the screen the whole UI is...just not right.
My question is, should I design for both portrait and landscape mode separately? If so how I do that?
ps. Actually I don't need rotation support for iPhone's app but I'm planning to make same app for iPad where every view has to be rotatable.thanks.
Edit:
just found good example
Easiest way to support multiple orientations? How do I load a custom NIB when the application is in Landscape?
I'd say it depends on the content. Sometimes it's enough to set the autoresizing of the UI elements in the Inspector of the Interface Builder properly and you get a satisfying effect, but there are cases where just resizing the view doesn't make the best use of the screen real estate. In your case for example just extending the segmented controls to the full width is probably not going to be as nice as arranging them next to each other to make the place for the text at the bottom.
If you are going to design for both modes separately, you can have them as different views and switch between the accordingly. Good example can be found in the 4th chapter of iPhone Cookbook. What the author does there is to switch the view when the orientation changes as follows :
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation
{
if ((interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
|| (interfaceOrientation == UIInterfaceOrientationLandscapeRight))
self.view = landscapeView;
else if ((interfaceOrientation == UIInterfaceOrientationPortrait)
|| (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown))
self.view = portraitView;
return YES;
}
I strongly recommend you look up the UIViewController class in docs and read it all (assuming you haven't already). The key methods you need include willRotateToInterfaceOrientation:duration:, described as follows:
willRotateToInterfaceOrientation:duration:
Sent to the view controller just before the user interface begins rotating.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
Parameters toInterfaceOrientation The
new orientation for the user
interface. The possible values are
described in UIInterfaceOrientation.
duration The duration of the pending
rotation, measured in seconds.
Discussion Subclasses may override
this method to perform additional
actions immediately prior to the
rotation. For example, you might use
this method to disable view
interactions, stop media playback, or
temporarily turn off expensive drawing
or live updates. You might also use it
to swap the current view for one that
reflects the new interface
orientation. When this method is
called, the interfaceOrientation
property still contains the view’s
original orientation.
This method is called regardless of
whether your code performs one-step or
two-step rotations.
Availability Available in iOS 2.0 and
later.
It sounds like you should also include:
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return NO;
}
Just set the autoresizingMask property of your control to
UIViewAutoresizingFlexibleWidth
I was looking for a solution and finally have chosen to set the layout elements programatically, as described in this article.
I'm trying to implement auto-rotation in my application that is basically UINavigationController with lots of UIViewControllers that get pushed onto it.
I've copy-pasted this in my first UIViewController (that gets pushed into UINavigationController):
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
Everything worked fine... However, if I paste in that code into second UIViewController (that first one pushes on top after some button click) - autorotation won't work. shouldAutorotateToInterfaceOrientation gets called when UIViewController is first initialized, but after it is visible and I rotate device - nothing happens.
So result is: first view gets rotated well - portrait/landscape... but after I click button and get into second view I remain stuck into that portrait or landscape, whatever was active.
I tried subclassing UINavigationController and setting shouldAutorotateToInterfaceOrientation there, but that also doesn't work.
What am I doing wrong?
There's a bug in the API that doesn't cause it to work for the second view. I solved it originally using setOrientation, but that's a private API and thus not a reasonable solution. I haven't released any new versions of the application while I try to figure out alternatives (and I don't think having customers upgrade to OS 4.0 is a solution). I'm thinking I'll need to manually keep track of the orientation and rotate my views manually to counteract the effects of the wrong rotation.
You need to implement this method in all views in the hierarchy