tags:

views:

111

answers:

3

I'm making an app where one of the objects needs to appear not to move or rotate during AutoRotation, but everything else needs to rotate and be repositioned. The way I did this is by manually rotating the object, and moving it into the same position, relative to the device, that it had prior to rotation. The problem is that it looks funny, appearing to rotate into the same position it had before.

If I suppress the animation effects during rotation, it would appear that the object never moved, and everything else just snapped into place, which is what I want. I haven't been able to find anything in the documentation that tells me how to do this though. How do I do this?

A: 

If you don't want rotation animations, overload -shouldAutorotateToInterfaceOrientation: in your UIViewController and return NO. You can then observe UIDeviceOrientationDidChangeNotification to receive manual orientation change notifications.

Rob Napier
I'm sorry but I don't understand what you mean by "overload -shouldAutorotateToInterfaceOrientation".
You should have a UIViewController subclass. In it, implement a method with the signature - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation. Have it return "NO". Read the UIViewController docs for more about this method. http://developer.apple.com/iphone/library/featuredarticles/ViewControllerPGforiPhoneOS/AutorotatingViews/AutorotatingViews.html
Rob Napier
That's overriding, not overloading.
AlBlue
Noted. ObjC can't overload and I've gotten sloppy in talking about it. The lack of overloading is noteworthy, and I've seen folks get bitten by it (pointing a notification handler at a one-parameter IBAction for instance, which works but is dangerous). Need to make a note to talk about that more at some point, and be more careful not to create new confusion.
Rob Napier
+1  A: 

When it comes to UIViewController rotation there are two ways you can set up so you get a chance to rotate and move your own views.

In the one-step process, in your UIViewController-derived class provide an implementation of willAnimateRotationToInterfaceOrientation. It gets called and you can kick off your object rotation so while the system is rotating everything else your object is getting counter-rotated so it looks like it's staying put. You'll want to calculate how much to counter-rotate and in which direction based on current interface orientation vs. new orientation.

The other way is to get notified to do custom rotation in two steps. For example, in the first half you can shrink the object down, move it, and rotate it part way then in the second half finish the rotation as you scale back up to normal size. It's a pretty clever way to make the rotation animation look smoother to the eye.

For the two-step process, you need to define two methods. willAnimateFirstHalfOfRotationToInterfaceOrientation gets called for the first half of the rotation (i.e. up to 45 degrees for a 90 degree rotation and at 90 degrees for an upside down flip). Once past that point the second half is called via willAnimateSecondHalfOfRotationFromInterfaceOrientation.

If your object has a 1:1 aspect ratio (i.e square or round) and in the middle of the view then the one-step process will probably work fine. But if it's a non-square object and has to move position (for example if it's at position 40, 60 in portrait but moves to 20, 100 in landscape) and maybe even needs a bit of scaling to look better then you may want to try the two-step process and see if it looks smoother.

If your object is inside its own individual UIView then it's pretty easy to schedule the rotations through UIView animations. Just create a transform through CGAffineTransformMakeRotation, then inside a pair of UIView beginAnimations/commitAnimations blocks set the transform property of the view to this value. You can tweak the timing through setAnimationDuration.

EDIT: Based on the comments, I'm adding some code to show how you could attach the view to the top-level window instead of to the view controller. Your object would then reside in this view instead of the one managed by controller (which is getting rotated). You still need to over-ride the UIViewController rotate methods, but instead of rotating an object under control of the view controller you would trigger a counter-rotation in the object on the top-level.

To add a view to the top-level window:

YourAppDelegate* windowDelegate = ((YourAppDelegate*) [UIApplication sharedApplication].delegate);
[windowDelegate.window addSubview:yourView];

Keep a reference to yourView somewhere you can get to, then in the UIViewController's willAnimateRotationToInterfaceOrientation counter-rotate yourView, i.e. calculate how much to rotate the view in reverse to where you're going--if the phone is turning 90-degrees clockwise, you'll want to rotate the view back 90 degrees counter-clockwise, etc. Then use UIView animations on yourView.

Ramin
The problem still exists, because the rotation still produces an animation effects on the UIView. I want it to look as if the UIView didn't rotate and resize, just the orientation changed, and the other objects within the UIView moved. I tried just rotating objects, and not the whole view, but then my alerts, etc appeared sideways.
The standard UIViewController rotation mechanism uses the two-step process (if you look at it carefully it scales down the view so it doesn't clip the edges too much then rotates and scales back up on second half. You can use the the same two-step process except scale *up* and counter-rotate your object by the same amount so it's effectively counteracting what UIViewController is doing. The other option is to add your object as a subview to the top-level UIWindow instead of the view controller, then manually rotate it from the UIViewController rotation call.
Ramin
I don't understand what you mean, can you post some example code?
I've updated the post. Hopefully it'll point you in the right direction.
Ramin
A: 

For some reason I'm not able to edit my question or post comments on any answers anymore.

Ramin: I really don't know what to do with that line of code you wrote or how to calculate how much to rotate the view in reverse. Your answers are assuming, I know way way more than I do. I'm in high school, I've never written a program before this, and I don't understand most of what I read in the apple documentation. I really appreciate your help, but you need to dumb it down to something I can understand.

Rob Napier: That's what I did at first, but all my alerts showed up sideways, whenever I was in landscape.