Handle orientation when showing a view - iphone

I have a few changes that get made to a UIView when the orientation changes. This works fine. The problem arises when adding the view after the phones orientation is already switched. This causes none of the rotate methods to be called and therefor does not give me the opportunity to make changes.
What would be the correct way of handling this, probably in ViewDidLoad? Would I be able to detect the current orientation at that point?
Bare in mind that its a few minor changes that I would need to make, so I dont want to load a different nib or anything like that
Thanks you very much :)
EDIT* just to clear things up: As I mentioned, the view is not even instantiated yet when the device orientation changes. The orientation changes to landscape -> the user clicks a button that shows another view -> this new view gets created and shown, but its default positioning is for portrait orientation -> when the view is shown, the elements I rearrange in the willAnimateRotationToInterfaceOrientation method are in the wrong position.

Typically I put the animations that occur when the user rotates the device (manipulating the frames of views mostly) in the willAnimateToInterfaceOrientation method. In it's skeleton form it would look like this:
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
{
//NSLog(#"willAnimateRotationToInterfaceOrientation: %d", toInterfaceOrientation);
if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation))
{
// portrait
}
else
{
// landscape
}
}
EDIT: In situations where I need to remember the device rotation for future use, I set up an ivar in my view controller class called currentOrientation (type int), and then do this:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
//NSLog(#"shouldAutorotateToInterfaceOrientation: %d", toInterfaceOrientation);
if (toInterfaceOrientation == UIDeviceOrientationPortrait || toInterfaceOrientation == UIDeviceOrientationPortraitUpsideDown ||
toInterfaceOrientation == UIDeviceOrientationLandscapeLeft || toInterfaceOrientation == UIDeviceOrientationLandscapeRight)
{
currentOrientation = toInterfaceOrientation;
}
return YES;
}
Then while running the methods in the view controller, I know which orientation the device is in.

Related

How can I lock the orientation when launching the app and unlock it when navigating to a Viewcontroller

I want to show an image to the user when they launch the App. This image is being shown for 20 seconds.
I'd like to have a functionality where ,when a user launches the App in Landscape, the App stays in Landscape. And when a user lauches the App in Portrait, the App stays in Portrait.
I was realy having a hard time configuring this in the Appdelegate so I made a seperate viewcontroller for showing this image. When the timer is finished I navigate to the next view where rotation should be enabled.
So how can I temporary lock the UI of the iPad?
Edit:
I fixed this by implementing a orientation check within viewDidLoad in the first Viewcontroller after my Appdelegate. For every orientation I saved a value. When performing shouldAutorotate: I first check for the saved value which disables orientation changes.
Solution in code:
- (void)viewDidLoad {
[super viewDidLoad];
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)) {
[[NSUserDefaults standardUserDefaults] setInteger:1 forKey:#"PortraitLandscapeIndicator"];
}
else {
[[NSUserDefaults standardUserDefaults] setInteger:0 forKey:#"PortraitLandscapeIndicator"];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
//the latest saved orientation is our orientation
if([[NSUserDefaults standardUserDefaults] integerForKey:#"PortraitLandscapeIndicator"] == 1){
return ((interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight));
}
else{
return ((interfaceOrientation == UIInterfaceOrientationPortrait) || (interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown));
}
}
Sounds like you will have to do something where a special viewController gets shown on start that in the loadView or init gets device orientation, then sets the views frame appropriately and which based on whatever mode portrait or landscape it is then only returns the allowed orientation from the [shouldAutorotateToInterfaceOrientation:].
After your timer is up, you can pass control to some other viewController to take it from there or subsequently allow other orientations.
But bottom line this is something I think you are going to have to do programmatically via whatever scheme works best for you.
you should save the initial interfaceOrientation (a property on the view controller) when you first display the image, then in your shouldAutorotateToInterfaceOrientation: method, return YES only if the orientation is the same as the initial saved value
once the timer is finished, you can allow rotations to any supported orientations

Any idea why this view is not rotating?

I'm working on a photo view controller to display some photos in portrait and landscape view as well. What I did is edit the -(BOOL)shouldAutorotateToInterfaceOrientation orientation with the code below but when testing in xcode (menu hardware > Rotate right) the view does not rotate in landscape. Any thing wrong in what I did ?
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
The view controller is a part of a tab based iphone app and this view is not root view: is this the problem ?
Also check your supported Orientations. For XCode 4 (Project->Summary(Tab)->Supported Device Orientation->Desired Orientations).
My first idea would be to just return true; to make sure there's no issue with the parameters being passed in / your comparison (it looks good to me but you never know).
Next would be, if this view is not directly attached to the window (or other top-level object if you're using xib's) you may have to also return true in any parent views. For the sake of testing you might just want to overwrite:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIIinterfaceOrientation)interfaceOrientation
{
return true;
}
for all view (controllers) in the tree.
this could be just a typo, but its not UIIinterfaceOrientation, its UIInterfaceOrientation
The method you want to override is shouldAutorotateToInterfaceOrientation. Your method signature is missing the Orientation on the end.
Make sure that the ViewController in which you implement this method, is the window's rootViewController.
Also, using return (interfaceOrientation != UIIinterfaceOrientationPortraitUpsideDown) is nicer to read. ;)
Does -shouldAutorotateToInterfaceOrientation get called at all? Try logging something in this method...
Your looking in the wrong place: in your RootViewController.m file look for the following code:
#elif GAME_AUTOROTATION == kGameAutorotationUIViewController
//
//lots of useless comments
//
return (UIInterfaceOrientationIsPortrait(interfaceOrientation) ); //THIS LINE HERE
the line that says return (UIInterface... Portrait) is the line that determines your app's rotating capabilities. You can change this to whatever to allow you to be able to rotate completely, keep it at a certain orientation, or whatever you desire...
also in this
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIIinterfaceOrientation)interfaceOrientation
{
/* return (interfaceOrientation == UIIinterfaceOrientationPortrait || interfaceOrientation == UIIinterfaceOrientationLandscapeLeft || interfaceOrientation == UIIinterfaceOrientationLandscapeRight); */ //GET RID OF ALL THIS CRAP
return true; //do this instead, and if this doesn't work, try return YES;
}
I'm not sure it's a type error or edition difference, in my latest Xcode the method is like this:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
and it works well, are you missing the "to" of the argument?

Hide UIView on device rotation - doesn't work when device is horizontal

I'm trying to hide an image in a view controller when the device is rotated. I'm posting a notification in PlayerViewController and am listening for it in the app delegate, which is responsible for the bannerView:
- (void)orientationChanged:(NSNotification *)notification {
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if ((orientation == UIDeviceOrientationLandscapeLeft) ||
(orientation == UIDeviceOrientationLandscapeRight)) {
bannerView.hidden = ([[self.navigationController visibleViewController] isKindOfClass:[PlayerViewController class]]) ? YES : NO;
} else {
bannerView.hidden = NO;
}
}
The PlayerViewController sends a notification and the app delegate hides the bannerView. However, when the device is laid flat on a table, the image shows. Works fine when the device is held vertically but horizontally the image appears... odd.
Here is the code to send the notification:
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation)) {
... hide other stuff in this view controller
}
Any ideas why this odd behavior is occurring?
Just one tidbit more information. In the simulator the image shows when the device is in upside-down orientation, even though I have:
- (BOOL)shouldAutorotateToInterfaceOrientation (UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationLandscapeRight || interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIDeviceOrientationPortrait) {
return YES;
} else {
return NO;
}
}
Your error might be happening because of when you're posting the notification.
willAnimateRotationToInterfaceOrientation is called before the orientation change takes place (hence the "will" in the method name). So if we're going from portrait to landscape, the current orientation may still be reported as portrait (it may not, it depends).
Now, the willAnimate... call returns the toInterfaceOrientation - the orientation that is going to happen.
You trigger your notification when you receive the willAnimate... call, and inside that notification call [[UIDevice currentDevice]orientation]: which will return portrait. Instead of requesting the orientation in your notification method you should instead pass the orientation provided in the willAnimate call.
If that wasn't clear, the one sentence summary: willAnimateRotationToInterfaceOrientation is called before the rotation changes.

iOS - UIViewcontroller detect rotation?

I am using willRotateToInterfaceOrientation to detect rotation and move items according to the orientation.
The problem is that when the page first loads this method doesn't get called so it doesn't try to move the objects to the correct location?
What is the solution?
You need to setup the interface according to the orientation
if ([UIDevice currentDevice].orientation == UIDeviceOrientationPortrait) {
// do something
} else if ([UIDevice currentDevice].orientation == UIDeviceOrientationLandscapeRight) {
// do something else
}
And repeat that for al the different device orientations
I manually detected the UIInterfaceOrientation from my UIApplication, and I manually called willAnimateRotationToInterfaceOrientation on viewDidAppear

Objective-c Change view when iphone is horizontal

How do I know when the iphone is vertically or horizontlly? I want to switch views depending on the iphone orentation.
Thanks
In a UIViewController subclass, you can override one (or more) of these methods:
willRotateToInterfaceOrientation:duration:
willAnimateRotationToInterfaceOrientation:duration:
didRotateFromInterfaceOrientation:
willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:
didAnimateFirstHalfOfRotationToInterfaceOrientation:
willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:
From the documentation notes for willRotateToInterfaceOrientation:duration::
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.
Like so:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if (toInterfaceOrientation == UIInterfaceOrientationPortrait)
{
// do a thing
}
else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
// some other thing
}
}