Keep back to origin position an UIImageView - ios

I'm now implementing an app, for iOS devices so in objective C, and i was asking how to keep back to origin position an UIImageView after a rotation ?
For example, i use my UIImageView like this :
CGAffineTransform initialPosition = CGAffineTransformMakeRotation(0);
CGAffineTransform finalPosition = CGAffineTransformMakeRotation(M_PI/2);
[UIView beginAnimations: #"Rotate animation" context: NULL];
MySuperUIImageView.transform = initialPosition;
[UIView setAnimationDuration:1.0];
[UIView setAnimationRepeatAutoreverses:NO];
[UIView setAnimationRepeatCount:1];
[UIView setAnimationDelegate:self];
MySuperUIImageView.transform = finalPosition;
[UIView commitAnimations];
But after, i made it desappear for a time, using :
MySuperUIImageView.alpha = 0.0f;
And when i re-use it, i want it to be in the first original position, with no rotation. Is it possible easily ?
Thanks in advance !

Yes. Very easily:
MySuperUIImageView.transform = CGAffineTransformIdentity;

Actually, there is. Since you're applying an affine transform to the view, you can reset all transforms applied to the view by setting its transform to CGAffineTransformIdentity which applies an identity transform matrix:
1 - 0 - 0
0 - 1 - 0
0 - 0 - 1
[mySuperUIImageView setTransform:CGAffineTransformIdentity];
Note: In Objective C, the convention is to start class names with a capital letter, and instances with a lower case.
As of iOS 4, Apple recommends using block based UIView animation. Here's an example of what I believe you're trying to attempt using updated code.
CGAffineTransform finalPosition = CGAffineTransformMakeRotation(M_PI/2);
[UIView animateWithDuration:1.0 delay:0.0 options:kNilOptions animations:^{
[mySuperUIImageView setTransform:finalPosition];
} completion:^(BOOL finished) {
[mySuperUIImageView setTransform:CGAffineTransformIdentity];
}];

Related

Trying to animate one UIImageView with two animations, only one animation has duration

What I want to do is flip this UIImageView in an instant, no animation, then I need it to float to it's intended position on the screen. Both of the transformations are working, but not the way I want them to.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
resultsEnemy.transform = CGAffineTransformMakeTranslation(0, 0);
[UIView commitAnimations];
resultsEnemy.transform = CGAffineTransformMakeScale(-1, 1);
This is the code I am using. Despite the fact that the scale code (which I am using to flip the UIImageView) is not part of the animation with the 0.5 duration, it is following those rules. How do I avoid this?
Applying two transforms like that isn't going to produce the result you expect. What you need to do is combine them into a single transform matrix. The following should work as expected.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
// Create two separate transforms and concatenate them together.
// Use that new transform matrix to accomplish both transforms at once.
CGAffineTransform translate = CGAffineTransformMakeTranslation(0, 0);
CGAffineTransform scale = CGAffineTransformMakeScale(-1, 1);
resultsEnemy.transform = CGAffineTransformConcat(translate, scale);
[UIView commitAnimations];
Edit: Based off of your clarification, you seem to be wanting something like this:
CGAffineTransform scale = CGAffineTransformMakeScale(-1, 1);
CGAffineTransform translate = CGAffineTransformMakeTranslation(0, 0);
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
resultsEnemy.transform = scale;
[CATransaction commit];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
resultsEnemy.transform = CGAffineTransformConcat(translate, scale);
[UIView commitAnimations];

Cannot stop Animation

I am using the following code to make text in a label blink :
- (void)blinkAnimation:(NSString *)animationID finished:(BOOL)finished target:(UILabel *) target {
NSString *selectedSpeed = [[NSUserDefaults standardUserDefaults] stringForKey:#"EffectSpeed"];
float speedFloat = (0.50 - [selectedSpeed floatValue]);
[UIView beginAnimations:animationID context:(__bridge void *)(target)];
[UIView setAnimationDuration:speedFloat];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(blinkAnimation:finished:target:)];
if([target alpha] == 1.0f)
[target setAlpha:0.0f];
else
[target setAlpha:1.0f];
[UIView commitAnimations];
}
and I am using the following code to make the animation Stop :
- (void) stopAnimation{
[self.gameStatus.layer removeAllAnimations];
}
Although the animation works fine, I cannot stop it.
Could you please help!
Thanks in advance....
The problem is that your animationDidStopSelector is being called when you manually stop your animation, but that method is just starting another animation. So you're stopping it ok, but you're immediately firing off another animation.
Personally, I'd suggest getting rid of the animationDidStopSelector and use the autoreverse and repeat features of the animation:
[UIView beginAnimations:animationID context:nil];
[UIView setAnimationDuration:speedFloat];
[UIView setAnimationDelegate:self];
[UIView setAnimationRepeatAutoreverses:YES];
[UIView setAnimationRepeatCount:CGFLOAT_MAX];
[target setAlpha:0.0f];
[UIView commitAnimations];
That should fix it, but as holex said, you should use block animation. I quote from the documentation: "Use of this method [beginAnimations] is discouraged in iOS 4.0 and later. You should use the block-based animation methods to specify your animations instead."
So, the equivalent block animation would be:
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat
animations:^{
self.gameStatus.alpha = 0.0;
}
completion:nil];
Whichever technique you use, your removeAllAnimations will now work as expected.
As an aside, when you stop animations, it will set alpha immediately to zero. It might be more graceful to stop the repeating animation and then animate the alpha from the current value to your desired final value. To do that, you'll want to grab the current opacity from the presentation layer and then animate alpha from that to whatever you want it to stop at (in my example 1.0, but you could use 0.0, too):
CALayer *layer = self.gameStatus.layer.presentationLayer;
CGFloat currentOpacity = layer.opacity;
[self.gameStatus.layer removeAllAnimations];
self.gameStatus.alpha = currentOpacity;
[UIView animateWithDuration:0.25
animations:^{
self.gameStatus.alpha = 1.0;
}];

Flip and Rotate

I have 2 views. I would like a card to flip and rotate along its axis to show the other view.
So when I click on view1, view1 should flip but flip in the sense that it rotates around the y-axis to show view 2.
I am using the FLIP directive in IOS, but that does not do the "rotate" that I am looking for:
[UIView transitionFromView:(self.displayingPrimary ? self.primaryView : self.secondaryView)
toView:(self.displayingPrimary ? self.secondaryView : self.primaryView)
duration: 2.0
options: (self.displayingPrimary ? UIViewAnimationOptionTransitionFlipFromLeft :
UIViewAnimationOptionTransitionFlipFromRight) | UIViewAnimationOptionShowHideTransitionViews
completion:^(BOOL finished) {
if (finished) {
self.displayingPrimary = !self.displayingPrimary;
}
}];
There are a couple of ways you can make one view flip to another using Quartz on iOS if you do not like the built in flip transformation. The following two code snippets both require you to #import <QuartzCore/QuartzCore.h> and also link against the QuartzCore framework. Note that both functions I wrote assume that both views are added as subviews with the same frame and one of them is hidden (setHidden:).
The first function will flip one view to another using 2D transformations. This is more efficient and all it really does is scale along the x axis. At high speeds, it looks pretty good, IMO.
+ (void)flipFromView1:(UIView*)v1 toView:(UIView*)v2 duration:(NSTimeInterval)duration completion:(void (^)(BOOL finished))completion
{
duration = duration/2;
[v2.layer setAffineTransform:CGAffineTransformMakeScale(0, 1)];
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
[v1.layer setAffineTransform:CGAffineTransformMakeScale(0, 1)];
} completion:^(BOOL finished){
[v1 setHidden:YES];
[v2 setHidden:NO];
}];
[UIView animateWithDuration:duration delay:duration options:UIViewAnimationOptionCurveEaseOut animations:^{
[v2.layer setAffineTransform:CGAffineTransformMakeScale(1, 1)];
} completion:completion];
}
The second function performs an actual 3D transformation. Note that if the views being rotated using this 3D transformation are over or under other subviews in 3D space then you could see those other views sticking through or getting hidden during this animation.
+ (void)flipFromView2:(UIView*)v1 toView:(UIView*)v2 duration:(NSTimeInterval)duration rToL:(BOOL)rToL completion:(void (^)(BOOL finished))completion
{
duration = duration/2;
v2.layer.transform = CATransform3DMakeRotation((rToL ? -1.57079633 : 1.57079633), 0, 1, 0);
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
v1.layer.transform = CATransform3DMakeRotation((rToL ? 1.57079633 : -1.57079633), 0, 1, 0);
} completion:^(BOOL finished){
[v1 setHidden:YES];
[v2 setHidden:NO];
}];
[UIView animateWithDuration:duration delay:duration options:UIViewAnimationOptionCurveEaseOut animations:^{
v2.layer.transform = CATransform3DMakeRotation(0, 0, 1, 0);
} completion:completion];
}

multiple animation blocks not working

I'm trying to translate and scale a view in the same block. For some reason the translate code is over riding the scaling and setting it at 100%. Please help.
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationCurveEaseInOut
animations:^{
fullView.transform = CGAffineTransformMakeTranslation(0.0, 425.0);
fullView.transform = CGAffineTransformMakeScale(0.8, 0.8);
} completion:^(BOOL finished) { }];
SOLUTION - Change 2 transform lines into one with CGAffineTransformConcat:
fullView.transform = CGAffineTransformConcat(CGAffineTransformMakeTranslation(0.0, 425.0), CGAffineTransformMakeScale(0.8, 0.8));
transform is a property that you are setting and then re-setting. What you need to do is construct a CGAffineTransform that consists of a combination of the two transforms. CGAffineTransformConcat() should nicely help you with that.

how can I interrupt/stop animation when I rotate?

For example, I use the animation in landscape status, duration is 5.0s, from status A to B; in the middle of the 5.0s, I may rotate the iPad from landscape to portrait. I want the animation stopped and make the UI status to C after I rotated.
I'm not sure my question is clear.
How can I do that?
my animation code:
- (void)moveImage:(UIImageView *)image duration:(NSTimeInterval)duration x:(NSNumber*)dx y:(NSNumber*)dy
{
// Setup the animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationBeginsFromCurrentState:YES];
// The transform matrix
float fx = [dx floatValue];
float fy = [dy floatValue];
CGAffineTransform transform = CGAffineTransformMakeTranslation(fx, fy);
//CGAffineTransform transform = CGAffineTransformMakeRotation(0.4);
//CGAffineTransform transform = CGAffineTransformMakeScale(2.0, 2.0);
image.transform = transform;
// Commit the changes
[UIView commitAnimations];
}
Starting and Stopping Explicit Animations has a section on starting and stopping core animations
willRotateToInterfaceOrientation:duration notifies you when the rotation begins.
So all have to do is 1) from 2)

Resources