How to allow only particular view to rotate? (iPhone) - iphone

I am installing AdMob's ad, and there is a GADBannerView.
After installing, a banner show, and if you click on it, a page will slide out coving the whole screen, and displaying advertising contents in it.
The question is, some advertising contents, such as video, had to be played landscape. However, I don't want other part of my application to rotate, as the app is not designed to be viewed in landscape.
So, how can I implement something which can achieve such function?

Try to use Notification for this. a notification calls a selector every time when ur device orientation is changed.
write this in your viewDidLoad:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(setScreenWithDeviceOrientation:) name:#"UIDeviceOrientationDidChangeNotification" object:nil];
and then define the selector as follows:
-(void)setScreenWithDeviceOrientation:(NSNotification *)notification
{
UIDeviceOrientation orientation=[[UIDevice currentDevice] orientation];
if(orientation==UIInterfaceOrientationPortrait) //Portrait orientation
{
// setView frame for portrait mode
}
else if(orientation==UIInterfaceOrientationPortraitUpsideDown) // PortraitUpsideDown
{
// setView frame for upside down portrait mode
}
else if(orientation==UIInterfaceOrientationLandscapeLeft)
{
// setView frame for Landscape Left mode
}
else if(orientation==UIInterfaceOrientationLandscapeRight) //landscape Right
{
// setView frame for Landscape Right mode
}
else
{
NSLog(#"No Orientation");
}
}
this method fired everytime when ur device changes orientation. Based on the current orientation you should adjust your view.
I hope this will help you.

Are you working with iOS 6? You should be able to just restrict what orientations your view controller handles in this case. For example, in your view controller that handles your GADBannerView, you can just put:
// Tell the system what we support
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
// Tell the system It should autorotate
- (BOOL) shouldAutorotate {
return NO;
}
// Tell the system which initial orientation we want to have
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
And that should make it so that your viewcontroller only supports portrait.

Have you looked at this question and answer? This explains how a single view can work in a certain orientation that is not supported by the rest of the application:
AutoRotate ONLY MpMoviePlayerControler iOS 6

Related

iOS7 / iOS6 Conditional Rotation Portrait / Landscape for different sections of App

Problem: A have an App that uses both Landscape mode (locked) and Portrait Mode (locked) for different parts of the app. Now I have a working solution however it doesn't seem correct and does have it's own problems.
Optimally I would love to force a orientation change. Thinking even about doing a view transformation if needed.
Basic flow of App:
HomeView (Portrait) (which has a few sub pushed views that are also portrait and locked to that).
LandscapeView (Landscape) (which has 5 pushed subviews that are also landscape)
Note:
HomeView has a link to LandscapeView
LandscapeView can go back to HomeView
At the end of the LandscapeView subviews it returns to the HomeView
Basic Image showing how this looks with the different view orientations. (The lines indicate flow of app, orientation of the images indicate how each screen should be )
Currently using the below implementation to call / set if the view is in portrait mode or landscape mode by [setLockedToPortait:YES] (for portrait view) etc.
This in term makes the query for what interface orientation to use from iOS if the device is rotated.
Now for the case of going to the LandscapeView, I show a temporary view over the top of the normal view asking to use to rotate their phone to landscape. (A temporary view is also shown when returning to the HomeView from a landscape view)
So once the user has rotated their device, it will trigger the correct orientation and then the temporary view will hide.
If the user then rotates their phone back to portrait at this point it will still be locked to landscape so will not trigger another view rotation (also no temp view will appear or anything)
Current Implementation Code::
// ---------------------- NavigationController (subclass of UINavigationController)
#interface NavigationController () {
BOOL isOrientationPortrait;
}
#end
#implementation NavigationController {
UIDeviceOrientation lastAccepted;
UIDeviceOrientation lastKnown;
}
-(void)setLockedToPortait:(BOOL)isLocked {
isOrientationPortrait = isLocked;
}
-(UIDeviceOrientation) getCurrentOrientation {
UIDeviceOrientation orientate = [[UIDevice currentDevice] orientation];
if(orientate == 0) { // needed for simulator
orientate = (UIDeviceOrientation)[UIApplication sharedApplication].statusBarOrientation;
}
return orientate;
}
// Deprecated in iOS6, still needed for iOS5 support.
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation
{
UIDeviceOrientation orientation = [self getCurrentOrientation];
[self setLastKnownOrientation:orientation];
if(isOrientationPortrait == YES) {
if([self isLastKnownPortrait] == YES) {
[self setLastAcceptedOrientation:orientation];
return YES;
} else {
return NO;
}
} else {
if([self isLastKnownLandscape] == YES) {
[self setLastAcceptedOrientation:orientation];
return YES;
} else {
return NO;
}
}
}
// iOS6/7 support
- (BOOL)shouldAutorotate
{
// find out the current device orientation
UIDeviceOrientation orientation = [self getCurrentOrientation];
[self setLastKnownOrientation:orientation];
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
if(isOrientationPortrait == YES) {
if([self isLastKnownPortrait] == YES)
{
UIDeviceOrientation orientation = [self getCurrentOrientation];
[self setLastAcceptedOrientation:orientation];
}
return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown);
} else {
if([self isLastKnownLandscape] == YES)
{
UIDeviceOrientation orientation = [self getCurrentOrientation];
[self setLastAcceptedOrientation:orientation];
}
return (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight );
}
}
-(void)setLastAcceptedOrientation:(UIDeviceOrientation)orient {
lastAccepted = orient;
}
-(void)setLastKnownOrientation:(UIDeviceOrientation)orient {
lastKnown = orient;
}
-(BOOL)isLastKnownPortrait {
return UIDeviceOrientationIsPortrait(lastKnown);
}
-(BOOL)isLastKnownLandscape {
return UIDeviceOrientationIsLandscape(lastKnown);
}
-(BOOL)isLastAcceptedPortrait {
return UIDeviceOrientationIsPortrait(lastAccepted);
}
-(BOOL)isLastAcceptedLandscape {
return UIDeviceOrientationIsLandscape(lastAccepted);
}
Current Problems:
Device rotations are always required after a view has loaded for the user going to Landscape mode from Portrait and vice versa.
If the user has the device orientation locked, this will not work at all.
When transitioning back from Landscape mode, and the user has already rotated their device to Portrait (in the last landscape view), the Portrait view's interface will be locked to a 'Landscape' layout until the user re-rotates their device (so currently I am just showing the overlay to rotate the device, but it is already rotated… very annoying for the user). Massive issue right now with the above implementation.
Would love to be able to:
Force an orientation change on the phone for the current view.
Set a preferred layout for a view which is forced between push/pops of views.
I've looked a lot at the other solutions on here and on the Apple Dev forums, however none seem to cover this problem, or still this orientation bug between the two views exists as well.
Thanks for any help or pointers! No advice will be discounted :D
--
Edit::
Solution Found thanks to #leo-natan!!
So instead of trying to force a change of orientation on the views. Just push a new modal view. This forces a change. You still need to above orientation code for managing rotations.
So what I have now in my HomeViewController:
LandscapeViewController * viewController = [[[LandscapeViewController ViewController alloc] init] autorelease];
UINib * nib = [UINib nibWithNibName:#"NavigationController" bundle:nil];
NavigationController *navController = [[nib instantiateWithOwner:nil options:nil] objectAtIndex:0];
[navController initWithRootViewController:viewController];
[self presentViewController:navController animated:YES completion:^{
// completion
}];
So it is necessary to re-add a new navigation controller for this modal view. Also note above 'presentViewController' is the new way of pushing Modal views.
Implemented this overloaded method for the managing of the view controller:
-(id)initWithRootViewController:(UIViewController *)rootViewController {
self = [super initWithRootViewController:rootViewController];
if(self){
}
return self;
}
Note: The above is not using storyboards. The problem may be solved by using storyboards and modally showing a view in the same fashion.
See my answer here, including a test project.
Basically, orientation can only be forced to change when presenting a view controller modally. For example, media playback in some apps. If you wish to transition from a view controller that can only be presented in portrait to a view controller that is only presented in landscape, you will need a modal presentation. Push will not work.

xcode - How do I keep views locked into portrait mode, but still allow one view to rotate?

I'm having a problem with device rotation. Except for ONE view, where I show a company splash screen, I want to lock all the remaining app views into Portrait display. In the project settings the supported orientations are Portrait and LandscapeLeft. In the 'Company Splash' it works fine and the view rotation is locked into LandscapeLeft no matter how I rotate the device. On all the other views when I rotate the device to the left the view alters instead of staying in portrait display. The methods are not even firing? If I remove Landscape left from the supported Orientations in the project, that screws up the 'Company Splash' view. I tried changing the shouldAutorotate return to NO, but that didn't help. Tried to work my way through the suggestions posted here, but that didn't help. If I put the following code into my AppDelegate.m, everything is locked into portrait mode and the 'Company Splash' crashes when accessed.
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}
How do I lock the view into portrait mode no matter how the device is rotated except for the one screen?
** method from the 'Company Splash' view. Again, works like it is supposed to.
-(NSInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeLeft;
}
** methods from all the other views, which rotate out of portrait when I don't want them to
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// IOS5 Only returning that it should rotate to potrait
return (interfaceOrientation == UIDeviceOrientationPortrait);
}
-(BOOL)shouldAutorotate
{
// forcing the rotate IOS6 Only
return YES;
}
-(NSInteger)supportedInterfaceOrientations
{
// return number or enum IOS6 Only
return UIInterfaceOrientationMaskPortrait;
}
I thought maybe it might be because a UITabBarController is the root controller and I'm in a ViewController off of that? The methods are not even firing?
Add an observer to the viewDidLoad method of the view you want to rotate like this :
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
addObserver:self selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:[UIDevice currentDevice]];
and then set the views according the the landscape view inside the orientationChanged method like this :
- (void) orientationChanged:(NSNotification *)note{
UIDevice * device = [UIDevice currentDevice];
switch(device.orientation)
{
case UIDeviceOrientationPortrait:
break;
case UIDeviceOrientationPortraitUpsideDown:
break;
case UIDeviceOrientationLandscapeLeft:
break;
case UIDeviceOrientationLandscapeRight:
break;
default:
break;
};
}
Slap this method into the view controller you want locked in a certain orientation.
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
just change to the orientation you want (the above locks it in landscape)
maybe u should allow all orientations, and lock portrait orientation in each class except company splash with
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationPortrait) {
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
} else {
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
}

How to change the orientation of the app without changing the device orientation in iphone app

I want to change the orientation of the app without changing the device orientation in iphone app.
I want to change my view from portraid mode to landscap mode programmatically.
And also want to know that will this be accepted by the apple store or not ?
Thanks
Now I got the solution from other that is as follow
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
when you add this line at that time one warning appear and for remove this warning just add bellow code on you implementation file..
#interface UIDevice (MyPrivateNameThatAppleWouldNeverUseGoesHere)
- (void) setOrientation:(UIInterfaceOrientation)orientation;
#end
and after that in bellow method just write this code if required..
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
But now want to know is this accepted by apple app store or not ?
thanks
use this line for programmatically change orientation...
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
and also when you add this line at that time one warning appear and for remove this warning just add bellow code on you implementation file..
#interface UIDevice (MyPrivateNameThatAppleWouldNeverUseGoesHere)
- (void) setOrientation:(UIInterfaceOrientation)orientation;
#end
and after that in bellow method just write this code if required..
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
// return NO;
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
i hope this help you..
:)
Add a class variable
Bool isInLandsCapeOrientation;
in viewDidLoad
set this flag to
isInLandsCapeOrientation = false;
Add the following function
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (!isInLandsCapeOrientation) {
return (UIInterfaceOrientationIsPortrait(interfaceOrientation));
}else {
return (UIInterfaceOrientationIsLandscape(interfaceOrientation));
}
}
To changing orientation from portrait to landscape, let it happens on a button action
- (IBAction)changeOrientationButtonPressed:(UIButton *)sender
{
isInLandsCapeOrientation = true;
UIViewController *viewController = [[UIViewController alloc] init];
[self presentModalViewController:viewController animated:NO];
[self dismissModalViewControllerAnimated:NO];
}
This works fine for me.
To change Orientation portraid mode to landscap mode use this code
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
use this code for programmatically change orientation...
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
If you want to change the particular view only in landscape..then u can try the following in its viewDidLoad
float angle = M_PI / 2;
CGAffineTransform transform = CGAffineTransformMakeRotation(angle);
[ [self.view] setTransform:transform];
The documentation describes the orientation property as being read-only, so if it works, I'm not sure you can rely on it working in the future (unless Apple does the smart thing and changes this; forcing orientation changes, regardless of how the user is currently holding their device, is such an obvious functional need).
As an alternative, the following code inserted in viewDidLoad will successfully (and somewhat curiously) force orientation (assuming you've already modified you shouldAutorotateToInterfaceOrientation ):
if (UIDeviceOrientationIsPortrait([[UIDevice currentDevice] orientation]))
{
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIView *view = [window.subviews objectAtIndex:0];
[view removeFromSuperview];
[window addSubview:view];
}
Clearly, this does it if the user is currently holding their device in portrait orientation (and thus presumably your shouldAutorotateToInterfaceOrientation is set up for landscape only and this routine will shift it to landscape if the user's holding their device in portrait mode). You'd simply swap the UIDeviceOrientationIsPortrait with UIDeviceOrientationIsLandscape if your shouldAutorotateToInterfaceOirentation is set up for portrait only.
For some reason, removing the view from the main window and then re-adding it forces it to query shouldAutorotateToInterfaceOrientation and set the orientation correctly. Given that this isn't an Apple approved approach, maybe one should refrain from using it, but it works for me. Your mileage may vary. But this also refers to other techniques, too. Check
SO discussion

Notification about iphone oriention

I want to get notification when a user is rotate the screen to landscape or portrait,
it is possible?
I find couple of article but i didn't found answer for this.
If you want to be notified when the device has been rotated you can either implement the shouldAutorotateToInterfaceOrientation: method in your view controller or you can register to receive the UIDeviceOrientationDidChangeNotification.
Before we start, the device orientation and the interface orientation can be different. The device may be landscape but the interface may remain portrait depending on how the app has been written. Device notifications are sent shortly before the interface orientation is changed to match the device orientation. If you don't want the interface orientation to change you should implement the shouldAutorotateToInterfaceOrientation: method in your view controller to return NO. This will stop the interface orientation being updated.
From your question it sounds like you want to receive notifications so I think you want to use the second method. You can enable UIDeviceOrientationChangeNotifications using:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
There is a corresponding:
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
You can register to receive the notifications in the normal way, using the NSNotificationCenter and registering to receive the UIDeviceOrientationDidChangeNotification:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
Finally, you would implement the method to be called when the notification is received as follows:
- (void)orientationChanged:(NSNotication *)notification {
UIDeviceOrientation = [[UIDevice currentDevice] orientation];
if (orientation == UIDeviceOrientationPortrait ||
orientation == UIDeviceOrientationPortraitUpsideDown) {
// Portrait
} else {
// Landscape
}
}
As you can see, the orientation can be accessed using the orientation instance method of UIDevice.
You need to add local notification in the landscape orientation in shouldAutorotateToInterfaceOrientation method
try like this:
if(interfaceOrientation == UIInterfaceOrientationLandscapeRight || UIInterfaceOrientationLandscapeLeft)
{
here schedule your local notification
}

Programmatically change device orientation in iPhone

I have navigation based app, when I click on any row in root view, the next view should come in Landscape mode.
I am not able to find a proper way to implement this. What I tried is:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
But this is not working. The view should open only in Landscape mode (not when user rotate it).
My sandbox app:
https://github.com/comonitos/programatical_device_orientation
The solution is easy:
in interface (h file) :
BOOL rotated;
in implementation (m file):
1. rewrite
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return rotated;
}
2 call [self setup]
-(void) setup {
rotated = YES;
[[UIDevice currentDevice] setOrientation:UIDeviceOrientationLandscapeLeft];
rotated = NO;
}
Try designing your view in landscape mode and in it's view controller, and in
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
.....
}
return No for portrait orientation and YES for landscape orientation
This will display your view in landscape mode.
you can force your Device to change Orientation.......using magic line in View will Appear
[[UIDevice currentDevice] setOrientation:UIDeviceOrientationLandscapeRight];
All the Best..
Here is some code from my landscape-view based app:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
if (interfaceOrientation == UIInterfaceOrientationLandscapeRight || interfaceOrientation == UIInterfaceOrientationLandscapeLeft){
return YES;
}
else {
return NO;
}
}
Put this in a landscape-based viewcontroller to have it display only in landscape mode and to switch between landscape left and landscape right. You will also need your xib to be landscape based.