How do I suppress animation during AutoRotation - iphone

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?

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.

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.

This may work:
Listen for willRotateToInterfaceOrientation
[UIView setAnimationsEnabled:NO];
Listen for UIDeviceOrientationDidChangeNotification
[UIView setAnimationsEnabled:YES];
Untested, but I know that does work for some cases.

Related

UIView 3D transform final frame location

I have a UIView which has an X origin that makes it off screen to the right. Then, I do a keyframe animation with CATransform3D:
[NSValue valueWithCATransform3D:CATransform3DMakeTranslation(-view.width, 0, 0)]
The problem is, after the animation completes, the view's frame is visually in the correct place, but it still thinks it's off screen, so I can't interact with it. Logging its frame property also shows that it's offscreen, but visually, it's not.
The fill mode for the animation is kCAFillModeForwards, so the final value of the animation sticks.
What is the solution to this problem, that is, interacting with this view after the animation and notifying the view that it is indeed visible?
You can use CAAnimation delegate method -animationDidStop:finished: to fix it when the animation done:
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
...
}
The better answer is to use UIView animation methods like animateWithDuration:animations:completion: (and variants on that method.)
Those methods let you do animations on the actual view properties, and when the animation is complete, the view is at it's actual destination location.
The center property is the easiest way to move views around. The frame property isn't valid if you've applied a transform, but the center property IS always valid for both reading and writing.
Core Animation only creates the illusion that your views move. The animation takes place on a display-only copy of the layer tree. You can query the properties of an animating layer by reading those same properties from the layer's presentationLayer. However, the view objects will not respond to the user interaction at their apparent location. The views still think they are at their original locations.
As the other poster said, you could use the animation completion delegate method to move the view to it's final location once the animation is over, but that's a lot of fussy work to do something that UIView animation does for you much more cleanly and simply.
Can you interact with the view even before you animate it?
is the view.userInteractionEnabled is set to YES??

Get objects in custom UIView objective c

I have a custom UIView which I named UIWheel that I am rotating upon TouchDown. This UIWheel has many UIViews which I would like to rotate at the opposite direction (so that they remain appearing upright even after rotation) .
How do I code to tell it to get all of the UIViews in the UIWheel and in TouchDown rotate in the opposite direction?
Using the subviews property, iterate over each subview and rotate it exactly the way you rotate the outer view, but in the opposite direction.
As another option, you can move the part which you do want to rotate into its own subview, and just rotate that subview. It's a little counter-intuitive to rotate every object, then rotate a large number of them back into position.

iphone - making the CGAffineTransform permanent

I am banging my head on the wall here due to this problem:
When I create a UIImageView this view has a certain orientation and size. Lets call this state "A".
This view responds to taps. It can be dragged around the screen.
At some point in the code I apply a CGAffineTransform to the view. Does not matter if the affine is a scale, a rotation, a translation or a combination of all. Does not matter also if the transform is absolute or relative. Not to mention the device can change its orientation and the view is autorotated to the correct orientation (that we can cay is a kind of rotation or transformation applied to the view).
The problem is: the moment I touch that object or try to animate its transparency or any other parameter, it "remembers" the state "A" and does all animations from that state, not from current state. If I simply touch the view, it returns instantly to state "A". The code is not doing it by itself. It is pretty annoying. How to I make a view assume its current state of transformations as the reset or initial state? In other words, how do I make a view forget its past transformations or states?
The only way I know is recreating the view, but this is a ridiculous way of doing this.
Is there any way to make this work as I described?
thanks
Afaik, all of the SDK animations automatically create a copy, perform the animation on the copy while hiding the original. In your code you'll have a getState line that starts this and creates the pointer to the animation object. To make it permanent at the end of your animation routine set the original objects view to the animation view.
Iirc it something like this, but I don't have my code samples in front of me:
myOriginalObject.view = myMnimationObject.view
Obviously do this before you release your animations but after you're done with the transforms.

iPhone Flip Transition - Can I get notified at the half way point

I have a single UIView for drawing any one of a set of items. That is, my one UIView subclass can be told to draw a square, circle, or triangle for example.
I'd like to have a transition to flip that view so that the UIView draws a different shape at the half way point, so it looks like I'm transitioning to a different view, but really I'm just redrawing the single view at the half way point of the transition.
Is there a way to do this, without resorting to using two different UIViews and swapping them out in the animation block? It would be a bit clumsy for me to rejig what I have to use the swap mechanism.
Ideally all I need is some callback or notification that the animation is at the half way point, and then I can redraw the view with the new shape then.
Thanks for any help!
Even if you did know the midpoint of your flip animation, I don't believe redrawing the content of the view mid-animation would do anything. I think that the contents of the view's layer are cached at the beginning of the animation and don't change as the animation proceeds. Also, your view would end up inverted, left to right, at the end of the animation if you didn't have another view behind it.
If you wish to do this as a custom animation, you could break this into two halves using something like Mike Lee's Lemur Flip implementation that I describe in this answer. After the first half of the animation, you could redraw the view's content and complete the animation, ending up back where you started.
However, to me it seems more clumsy to not switch views in response to the transition. It certainly will take a lot more code to do.
you can try to do smth like this. For example, your animationDuration property is set to 2.0f. so, the half way point is 1 second, so you can use
[self performSelector:#selector(yourCallbackMethod) withObject:nil afterDelay:1.0f];
The only way I know of that you could do this is to re-create the animation using Core Animation and then monitor the animation in the presentationLayer using a timer. There is no KVO available in Core Animation Layers so you have to monitor it explicitly.
In other words, it's probably not worth it. I suggest you think of a different way to solve your problem.

Flipping UIViews From Top / Bottom

I'm well aware that there are only two available UIView transitions, UIViewAnimationTransitionFlipFromLeft and UIViewAnimationTransitionFlipFromRight. I'm wondering if there is anyway that I can implement / emulate a UIViewAnimationTransitionFlipFromTop or UIViewAnimationTransitionFlipFromBottom.
The only way I can think to do this is by flipping the x axis with the y axis, but I've not seen any information about how to do this. Just setting the coordinates of each axis won't fix the issue as the x-axis till remains the x-axis.
Does anyone have any ideas how this can be accomplished?
You can do this by applying a CATransform3D to your main view's CALayer, with your secondary view's CALayer behind it. In this response, I point to a Mac implementation of this animation by Mike Lee. You should be able to reuse a significant portion of that code to recreate this effect on the iPhone.
Guess you'll have to use a UIView animation block with a 3D rotation transform of 90 degrees, have the Core Animation delegate call you when that's done, swap the view with the new one (3D rotated on the other side) and chain with the last 90 degrees for the new view...
Although its not exactly what you want, there are two built-in animations that you didn't mention: UIViewAnimationTransitionCurlDown and UIViewAnimationTransitionCurlUp.
CurlUp looks like someone is peeling the view from the bottom up to the top, and CurlDown looks like the view is being unrolled down on top of the screen from top to bottom. You should at least give them a look, as they are easy to use.