I\'m doing an app where I have a GLES view which I don\'t want to be auto-rotated, and UIKit views on top of that, which do need to be auto-rotated.
Apparen
There isn't a good way to do this any better than what you proposed.
Are you sure you don't just want to rotate the OpenGL views too? If your application is limited to the ES 2.0 devices and later on iOS 4.2, there is no longer any performance penalty to using UIViewController rotation for OpenGL views.
Wouldn't it be simpler to just draw your OpenGL content sideways when rotated? Just apply a rotation in your renderer to undo the rotation of OpenGL view.
You may see an unacceptable jump back to the original rotation, but you could address that easily. You could animate the return rotation, once the view is finished rotating. Or you could override willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:
and willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:
to animate the content staying in place during the interface rotation.
So I found out how it works behind the scenes; Frogblast is right, there isn't any substantially better way to do it.
What happens is that when a view gets added to a window that has no subviews, that view's controller is automatically the "rotation authority"; If that view controller returns NO from shouldAutorotateToInterfaceOrientation, no other views will rotate either. However, subsequent views (with controllers) added to the window are still allowed not to rotate, even if the "rotation authority" does rotate.
Unclear to me why they've made it like this, but there you have it.
I've come up with a different strategy for a similar situation. In my case I allow all the views to rotate, but then use a transform to bring the view I want to keep steady back to its original orientation. This works because the "non-rotating" view is square, but with a bit more math it could work for other shapes as well. Here's what I put in my willRotateToInterfaceOrientation:duration:
switch (toInterfaceOrientation) {
case UIInterfaceOrientationPortrait:
steadyView.transform = CGAffineTransformIdentity;
break;
case UIInterfaceOrientationLandscapeLeft:
steadyView.transform = CGAffineTransformMakeRotation(M_PI_2);
break;
case UIInterfaceOrientationPortraitUpsideDown:
steadyView.transform = CGAffineTransformMakeRotation(M_PI);
break;
case UIInterfaceOrientationLandscapeRight:
steadyView.transform = CGAffineTransformMakeRotation(3*M_PI_2);
break;
}
The steadyView
is s subview of the controller. This seems to do the trick.