How to make a CGAffineTransform permanent? - iphone

According to this answer there's a way to make a CGAffineTransform permanent:
iphone - making the CGAffineTransform permanent
but it's not explained... the answer tells about a copy that is generated by the animation but isn't clear how to get it and assign to the original object, so this is the code, how to make it permanent?
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationRepeatAutoreverses:NO];
[UIView setAnimationRepeatCount:1];
[UIView setAnimationDelegate:self];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
float angleRadians = 180 * ((float)M_PI / 180.0f);
CGAffineTransform t = CGAffineTransformMakeRotation(angleRadians);
self.myView.transform = t;
[self.myView setCenter:CGPointMake(160, 220)];
[UIView commitAnimations];
Thanks

You can try going a level down to Core Animation and apply transform animation with following properties:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform"];
animation.fromValue = [NSValue valueWithCATransform3D: t];
animation.toValue = [NSValue valueWithCATransform3D: t];
animation.duration = 0.0;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeBoth;
[yourView.layer addAnimation:animation forKey:#"transform"];
Then you can do other core animations and it should retain the transform. Don't forget to import QuartzCore framework.

In iOS 4.0 or greater Apple recommends using Block based animations
reference: What are block-based animation methods in iPhone OS 4.0?
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationOptionCurveEaseOut
animations:^{ self.myView.transform = CGAffineTransformMakeRotation(M_PI) }
completion:NULL];
Not sure if this will solve your problem exactly, but it is a step in the right direction.

Related

Fade-In Fade-Out Animation for UIImageViews?

I have two UIImageView - leftSide and rightSide, which I would like to fade in and then fade out, one after the other, in a loop.
How do I do this in Xcode? I tried CABasicAnimation but this did not work (I'm not sure why, no errors at all, the images do not fade).
Thanks!
EDIT: This is the code I was using:
-(void)leftSideFade{
CABasicAnimation *blink;
blink = [CABasicAnimation animationWithKeyPath:#"opacity"];
blink.duration = 1.0;
blink.repeatCount = 5;
blink.autoreverses = YES;
blink.fromValue = [NSNumber numberWithFloat:1.0];
blink.toValue = [NSNumber numberWithFloat:0.0];
[leftSideStart.layer addAnimation:blink forKey:#"animateOpacity"];
[self rightSideFade];
}
-(void)rightSideFade{
CABasicAnimation *blink;
blink = [CABasicAnimation animationWithKeyPath:#"opacity"];
blink.duration = 1.0;
blink.repeatCount = 5;
blink.autoreverses = YES;
blink.fromValue = [NSNumber numberWithFloat:1.0];
blink.toValue = [NSNumber numberWithFloat:0.0];
[rightSideStart.layer addAnimation:blink forKey:#"animateOpacity"];
[self leftSideFade];
}
- (void)fadeIn
{
[UIView beginAnimations:#"fadeIn Animation" context:nil];
[UIView setAnimationDuration:1.0];
imageView.alpha = 1.0;
[UIView commitAnimations];
}
Try this to.
Try using the following :
- (void) fadeinRightFadwOutLeft {
[UIView beginAnimations:#"start" context:nil];
[UIView setAnimationDuration:1.0];
rightSide.alpha = 0.0;
leftSide.alpha = 1.0;
[UIView commitAnimations];
}
- (void) fadeinLeftFadwOutRight {
[UIView beginAnimations:#"start" context:nil];
[UIView setAnimationDuration:1.0];
leftSide.alpha = 0.0;
rightSide.alpha = 1.0;
[UIView commitAnimations];
}
How about a simpler way with UIView animateWithDuration:animations:completion: ?
There you just change alpha of your views and they will fade in/out
Here is a sample code:
[UIView animateWithDuration:duration
animations:^
{
//Here you set values you want to see in the end of animation
leftView.alpha = 0.0f;
rightView.alpha = 1.0f;
}
completion:^(BOOL finished)
{
//something to do after animation finished
}

How Do You Combine Scale and Translation Animation

I am attempting to do an UIView animation where my image starts at the top left of the screen and expands to the original size and place in the middle of the screen. So far I have been able to make it do this separately but when I try to combine these animations it will only do the scale animation.
Is there a way I can make this work with Scale and Translation at the same time?
Here is what I have so far:
CGAffineTransform setpointTrans = CGAffineTransformMakeTranslation(-200.0f, -200.0f);
CGAffineTransform setpointScale = CGAffineTransformMakeScale(0.0f, 0.0f);
_RSEImage.transform = CGAffineTransformConcat(setpointTrans, setpointScale);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
CGAffineTransform scaleTrans = CGAffineTransformMakeScale(1.0f, 1.0f);
CGAffineTransform lefttorightTrans = CGAffineTransformMakeTranslation(0.0f,0.0f);
_RSEImage.transform = CGAffineTransformConcat(scaleTrans, lefttorightTrans);
[UIView commitAnimations];
Ok I figured it out, here is what I changed:
_RSEImage.transform = CGAffineTransformMakeScale(0.0f, 0.0f);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
CGAffineTransform scaleTrans = CGAffineTransformMakeScale(1.0f, 1.0f);
CGAffineTransform lefttorightTrans = CGAffineTransformMakeTranslation(200.0f,200.0f);
_RSEImage.transform = CGAffineTransformConcat(scaleTrans, lefttorightTrans);
[UIView commitAnimations];
You can use this, animation blocks, also (from iOS4):
[UIView animateWithDuration: 5
delay: 0
options: (UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction)
animations:^{_RSEImage.center = CGPointMake(300, 300) ; _RSEImage.transform = CGAffineTransformScale(CGAffineTransformIdentity, 2.0, 2.0);}
completion:^(BOOL finished) { }
];
Relevant official doc here: link
Nice tutorial there: link
Hope it helps!

Multiple animations after each other

I'm having a problem I can't find any solution for it.
So basically, I'm having a compass that I want to "pop in"/"pop out" into the view, and then start to update heading, but heading stops updating after I dismiss/pop out the compass.
Like: user wants compass-> presses button-> compass pops up-> starting to rotate compass needle-> user don't want compass anymore/dismisses compass-> compass pops out of view.
So my question is: If i make one animation, the other animation stops, how do i make it possible for both to run after each other?
In showCompass:
(IBAction) showCompass:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
directionsArrow.center = CGPointMake(160, 410);
[UIView commitAnimations];
In locationManager:
float oldRadian = (-manager.heading.trueHeading * M_PI/180.0f);
float newRadian = (-newHeading.trueHeading * M_PI/180.0f);
CABasicAnimation *animation;
animation=[CABasicAnimation animationWithKeyPath:#"transform.rotation"];
animation.fromValue = [NSNumber numberWithFloat:oldRadian];
animation.toValue = [NSNumber numberWithFloat:newRadian];
animation.duration = 0.5f;
[directionsArrow.layer addAnimation:animation forKey:#"animateMyRotation"];
directionsArrow.transform = CGAffineTransformMakeRotation(newRadian);
In dismissCompass:
-(IBAction) dismissCompass {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
directionsArrow.center = CGPointMake(160, 410);
[UIView commitAnimations];
[locationManager stopUpdateHeading];
}
New code:
*Show:*
[UIView animateWithDuration:1.f
animations:^{
compassDial.center = CGPointMake(160, 504-92);
pushView.center = CGPointMake(160, 500-92);
//directionsArrow.center = CGPointMake(160, 502-92);
} completion:^(BOOL finished) {
directionsArrow.hidden = NO;
[locationManager startUpdatingHeading];
}];
In locationManager:
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading{
float oldRadian = (-manager.heading.trueHeading * M_PI/180.0f);
float newRadian = (-newHeading.trueHeading * M_PI/180.0f);
CABasicAnimation *animation;
animation=[CABasicAnimation animationWithKeyPath:#"transform.rotation"];
animation.fromValue = [NSNumber numberWithFloat:oldRadian];
animation.toValue = [NSNumber numberWithFloat:newRadian];
animation.duration = 0.5f;
[directionsArrow.layer addAnimation:animation forKey:#"animateMyRotation"];
directionsArrow.transform = CGAffineTransformMakeRotation(newRadian);
Dismiss:
[UIView animateWithDuration:1.f
animations:^{
compassDial.center = CGPointMake(160, 700);
directionsArrow.center = CGPointMake(160, 700);
} completion:^(BOOL finished) {
[locationManager stopUpdatingHeading];
}];
Thanks in advance.
I'm assuming the two animations you want to happen at the same time are the rotation and the moving of the frame?
The easiest thing to do to ensure the animation is smooth and follows what you expect is to place the compass inside another view.
You can then animate the frame of the compass' parent to make the compass move in and out and apply the rotation just to the compass itself.
Show
[UIView animateWithDuration:1.f
animations:^{
compassContainer.center = CGPointMake(160, 410);
}];
Rotation
// The code you already have changing the transform of directionsArrow
Dismiss
[UIView animateWithDuration:1.f
animations:^{
compassContainer.center = CGPointMake(160, 410);
} completion:^(BOOL finished) {
[locationManager stopUpdateHeading];
}];
As Paul.s mentioned in the comments, that is not the current preferred way to do animations. And what you ask is really quite easy with the block method of animations. Have a look at the documentation, and here is a short example.
-(IBAction)animateDelete:(id)sender
{
[UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationOptionCurveEaseIn
animations:^{
// Your first animation here...
}
completion:^(BOOL finished) {
// Do some stuff
[UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut
animations:^{
// Your second animation here...
}
completion:^(BOOL finished) {
// Do some stuff
}
];
}
];
}

Animation, like when you delete from iPhone Photo Gallery

I try to implement the animation:
when you enter iPhone Gallery, press the image, you see full-screen image. Below you can see toolbar with trash button. When you press this button, the image is being deleted with animation.
I try to implement this, but I don't know, how to implement the transform of image, apple use.
This is the best, I could do:
[UIView transitionWithView:self.view duration:0.1 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
[self.view addSubview:scrollImageView];
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
CGRect frame = scrollImageView.frame;
frame.size = CGSizeMake(frame.size.width * 0.75, frame.size.height * 0.75);
frame.origin = CGPointMake((size.width - frame.size.width) / 2, (size.height - frame.size.height) / 2);
scrollImageView.frame = frame;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
CGRect frame = scrollImageView.frame;
frame.size = CGSizeMake(frame.size.width * 0.05, frame.size.height * 0.05);
frame.origin = CGPointMake(size.width, size.height);
scrollImageView.frame = frame;
CGAffineTransform transform = scrollImageView.transform;
CGAffineTransform rotatedTransform = CGAffineTransformRotate(transform, 45 * 3.14 / 180);
scrollImageView.transform = rotatedTransform;
} completion:^(BOOL finished) {
[scrollImageView removeFromSuperview];
}];
}];
}];
Thank you in advance.
Update
As I understand, I can't do this animation with Core-Animation, but may anyone can advice me the animation the most simular to iPhone Gallery animation, but without using OpenGL?
You can use following example for this animation:
UIView *senderView = (UIView*)sender;
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"transform"];
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
anim.duration = 0.125;
anim.repeatCount = 1;
anim.autoreverses = YES;
anim.removedOnCompletion = YES;
anim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.2, 1.2, 1.0)];
//[senderView.layer addAnimation:anim forKey:nil];
UIBezierPath *movePath = [UIBezierPath bezierPath];
[movePath moveToPoint:icon.center];
[movePath addQuadCurveToPoint:senderView.center
controlPoint:CGPointMake(senderView.center.x, icon.center.y)];
CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:#"position"];
moveAnim.path = movePath.CGPath;
moveAnim.removedOnCompletion = YES;
CABasicAnimation *scaleAnim = [CABasicAnimation animationWithKeyPath:#"transform"];
scaleAnim.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
scaleAnim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1.0)];
scaleAnim.removedOnCompletion = YES;
CABasicAnimation *opacityAnim = [CABasicAnimation animationWithKeyPath:#"alpha"];
opacityAnim.fromValue = [NSNumber numberWithFloat:1.0];
opacityAnim.toValue = [NSNumber numberWithFloat:0.1];
opacityAnim.removedOnCompletion = YES;
CAAnimationGroup *animGroup = [CAAnimationGroup animation];
animGroup.animations = [NSArray arrayWithObjects:moveAnim, scaleAnim, opacityAnim, nil];
animGroup.duration = 0.5;
[icon.layer addAnimation:animGroup forKey:nil];
I have modified the code, you have to perform following changes in it, set the sender view as self.view, and change the ending point of animation (which is currently senderView.center) according to your requirement
I know its a bit late. But, you should check Ciechan's solution named BCGenieEffect. Can be found here. Its pure Core Animation and very easy to understand. I think that's what you are looking for.
Good luck
At this point the exact animation you are talking about cannot be done using Core Animation or UIKit. You would need to use OpenGL and apply the image as a texture and do your animation in there.
I think you are talking about the "suck" transition animation.
It is possible to trigger it, but it is a private transition, and Apple may reject your app if you use it.
This code should do it, using a transition code of 103:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition: transtionIndex forView:containerView cache:NO];
[containerView addSubview: newView];
[oldView removeFromSuperview];
[UIView commitAnimations];
Or search the net for a Core Image transition called "suckEffect"

Core Animation for UIView.frame

I'm trying to do a simple animation of moving the frame of two views. Basically hiding the Ad until it is loaded, and then move the frame up from the bottom, along with the view that starts at the bottom, and then will move up also when the Ad pushes it up. The start and end positions are correct, but I don't see it being animated. Is this correct? Thanks.
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:#"frame"];
animation.duration = 1.0;
CGRect adFrame = CGRectMake(self.adBanner.frame.origin.x, self.adBanner.frame.origin.y - self.adBanner.frame.size.height, self.adBanner.frame.size.width, self.adBanner.frame.size.height);
self.adBanner.frame = adFrame;
[self.adBanner.layer addAnimation:animation forKey:#"frame"];
CGRect buttonViewFrame = CGRectMake(self.ButtonView.frame.origin.x, self.adBanner.frame.origin.y - self.adBanner.frame.size.height, self.ButtonView.frame.size.width, self.ButtonView.frame.size.height);
self.ButtonView.frame = buttonViewFrame;
[self.ButtonView.layer addAnimation:animation forKey:#"frame"];
For something as simple as this, you don’t really need to use Core Animation directly—UIView’s built-in animation system should suffice.
[UIView animateWithDuration:1.0 animations:^{
self.adBanner.frame = adFrame;
self.ButtonView.frame = buttonViewFrame;
}];
or, if you’re targeting pre-4.0 iOS,
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
self.adBanner.frame = adFrame;
self.ButtonView.frame = buttonViewFrame;
[UIView commitAnimations];
[UIView beginAnimations : #"Display notif" context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationBeginsFromCurrentState:FALSE];
CGRect frame = mainView.frame;
frame.size.height -= 40;
frame.origin.y += 40;
mainView.frame = frame;
[UIView commitAnimations];