Background UIImageView that doesn't get rotated - iphone

I have this UINavigationController-based iPad app that supports all 4 orientations. When I rotate the device, I'd like the background image to stay still and only have the UI on top of it get rearranged/rotated.
I've succeeeded by returning NO to the UIViewController shouldAutorotateToInterfaceOrientation: and handle the orientation myself using UIDeviceOrientationDidChangeNotification
Since only the current view gets rotated (and not the whole window), the UINavigationController push animation doesn't get adjusted. So when you're holding the iPad in landscape right, it pushes the view from the bottom. When you're holding it upside-down, it pushes the view from the left (it should always be from the right).
Any better way to have that background image remain steady while rotating everything else? Or fixing the UINavigationController push animation? I'd like to stick with the controllers if possible (ie not having to play around with manually animating view frames, etc).

As you have seen, UINavigationControllers are very particular about orientation.
I think you are probably better off rotating the background every time the interface is rotated.

Related

Why Status Bar rotates and view remains portrait

My rootViewController is a UITabbarController and contains UINavigationControllers.
In order to restrict rotation, since iOS6, on some but not all views, I have subclassed both of the these controllers to respect the shouldAutorotate response of their topmost or visible view.
This all works just perfectly... most of the time.
In one case, starting from a view (UITableviewController) that does not allow rotation.
I push a view that does allow autorotate, rotate to landscape then back to portrait.
Then when I pop the view, all appears well.
But now if I rotate the device, the status bar alone rotates, leaving a blank space at the top and covering a part of the left side of the current view. The current view does not rotate (as it should not). Only the status bar rotates, back and forth. The view remains responsive, receives touches and works as normal, doesn't resize or respond to rotation in any way (as it should not).
This behavior continues until I kill and restart the app. Once it happens I have found no other way to make it stop. On restart all works properly again and will work properly for an indeterminate duration. I can sit there pushing, popping, rotating back and forth to my hearts content with no issues.
I have never been able to recreate this in simulator.
It happens for no apparent reason, I cannot make it happen. I'd say 85% of the time it works properly. I thought I had it fixed many times when it did not occur for days or even weeks. Then, out of the blue it happens again.
I cannot find a post in any forums which describe this behavior, so I am not finding even a place to start to debug. How could the status bar swing from top to side and the view does not resize or rotate or respond in any way. If I knew how to make that happen, I would have a place to start.
I experienced the same problem when adding a subclassed UIWindow (in my case, a status bar overlay).
The solution was to set the rootViewController of this new UIWindow to a subclassed UIViewController that had -(BOOL)shouldAutorotate implemented. This prevented the status bar from rotating when it wasn't supposed to.

Force orientation change in container view controller

I've created a container view controller in which I can embed a child view controller (using the new iOS 5 API). When a child view controller is embedded that only supports the portrait orientation, and the device is currently in landscape orientation, I want to force a rotation to portrait.
I found the [UIViewController attemptRotationToDeviceOrientation] method which almost does this, but not quite. It actually works the opposite way, so that if the child view controller is embedded, and the device is in portrait orientation, I can rotate to landscape (but the view controller will remain portrait), then dismiss the embedded view controller, and it will automatically rotate to landscape.
Is there any way to force the container view controller to rotate when embedding a child view controller that doesn't support the current orientation?
I'll bet money this isn't a satisfying answer, BUT...I think you have to abandon rotation and move to an affine transform (of the subview) of 90 degrees. Rotation is a physical act of the user, and try as we might we can't actually rotate the device. However, a transform is within your power. You can always set it back to the identity once the user complies and rotates the device to the proper orientation.
Have fun & good luck,
Damien

iPhone/iOS SDK: Autorotate main view, but not child view?

Here's what I'm trying to do.
I have a single view ("primaryView"), controlled by a customized view controller. primaryView contains a scrollview, which contains an image. Sitting on top of the scroll view (NOT inside it) is a small view ("buttonsView") containing a few buttons.
Basically, when the user rotates the phone, I want buttonsView to autorotate to match the new orientation, but I want the scrollview to remain exactly as it is, and NOT rotate.
Is there a way to do this? Right now, primaryView is autorotating, and taking both subviews (the scrollview and buttonsView) with it, which is no good.
Thanks!
The system will not autorotate unless all visible views consent to autorotation. What you can do, then, is to detect orientation changes, and set an appropriate affine transform for the non-rotating views, essentially to undo the system's rotation.
You can use willRotateToInterfaceOrientation:duration: to fade out the controls, then didRotateFromInterfaceOrientation: to fade them back in at the correct location.

iPhone force rotation

I have been reading a ton on rotation, but not finding a solution to my query. Here goes:
I have a portrait application with a tabbar and hidden navigation controller in my tab. At a point in the app, the next view must be landscape.
The XIB layout has been done in landscape, so I want to bring up the xib without any translation or pixel moving code. (not thinking this is required) I have tried just pushing the view (remains in portrait), shifting the view using various methods (non seem to line thing up properly).
Is there a way to tell the view that it is already laid out for landscape prior to it being opened?
Thanks in advance!
Found it, this code does the trick in the viewdidload:
self.view.transform = CGAffineTransformIdentity;
self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
self.view.bounds = CGRectMake(0.0, 0.0, 460.0, 320.0);
Still have 1 odd thing. No matter what I do to set the navigation bar to hidden, it does not rotate, and stays at the left side of the view.
[[self navigationController] setNavigationBarHidden:YES animated:NO];
Has anyone seed this behavior and solved?
I'm positive that you cannot 'force' a rotation. The system decides when to change the orientation of the device; so the 'orientation' properties are essentially read-only. I looked into this same problem a long time ago when I wanted to make sure a particular view always displayed in one orientation.
Due to this, most apps allow all of their views and view controllers to work in any of the orientations the app supports. I've found that trying to restrict the behavior of some views and view controllers ultimately creates more hassle, and can cause issues when transitioning between views and view controllers.
The code you posted will work for your view. You are not actually changing the orientation at all; your view is just behaving like it has been rotated by drawing in a rotated fashion. I'm not sure if you can do the same thing to the navigation bar or not, but it's worth a shot. If you are able to control the view properties of the navigation bar (it is a UIView as well), applying the same pattern you are using for your custom view should work.
Most apps that want a view to only be in landscape ultimately force their entire app to be in landscape. For instance, Flight Control only supports one orientation. Thus, the drawing code is pretty simple; regardless of orientation, just draw the view and rotate it to the one orientation it supports (either landscape left or right).
Your app's design wouldn't be that easy... it sounds like you are not designing a full-screen app. You would have to worry about the navigation bar and status bar being properly drawn.

iPhone autorotation only on specific screens in under a navigation controller

This is just an example of the basic problem I'm having, so don't worry if this situation sounds a bit pointless ;)
Let's say I have an app that's mainly a UINavigationController just two levels deep. The top level is a table with a list of image filenames, and the second level has just a UIImageView showing the image for the filename you tapped.
For an app such as this, does anyone know a good way to allow the table at the top level to autorotate while keeping the second level of images fixed in portrait mode?
So far I've been able to almost get there... but when I tap a filename while in landscape mode, the image slides into view in the wrong orientation even if the second level view controller's shouldAutorotateToInterfaceOrientation returns yes for only portrait modes.
There was no good way to do this in iPhone OS 2.x, but in 3.0, they've dramatically improved it.
In 2.x, the shouldAutorotateToInterfaceOrientation: delegate method was only obeyed for changes to the orientation, so you'd get the behavior you describe: if it was rotated in another view controller, it would stay rotated through pushes and pops even if the new view controller didn't support rotation to that orientation.
In 3.0, UINavigationController polls shouldAutorotateToInterfaceOrientation: on each push or pop and obeys what it returns the way you'd expect, e.g.: if you're currently rotated in Landscape Left orientation, and you push an instance of a view controller that only supports Portrait orientation via shouldAutorotateToInterfaceOrientation:, it automatically and instantly flips the logical orientation and slides in the new view the correct way in Portrait orientation.
Note that this will only work on applications linked against (and therefore requiring) 3.0. For applications linked against 2.x, it will emulate the old behavior.
The problem is that if you use auto rotation the entire UI (including the UIWindow instance I believe) is rotated.
Anything pushed onto the navigation controller at this point will be done in landscape.
So when you push the imageview, that is exactly what you get.
To get this to work, you have to either:
Handle the rotation of the root view
manually (using a transform)
Unrotate the image view by -PI/2
using a transform.
Either way you have to perform the transforms manually to get this to work.
As a side note, this may be bad UI design. As a user, I would expect as I drill down for images to appear rightside up. But this is without knowing the exact context of your app.