I need to give some stretch & skew animation to a UIView upon pressing a button or completion of a task.
Most of the animation applied to UIView are usually applied when they are added to or removed from a UIView but how can I accomplish that with a view already added to view.
Animation could be anything as long as it catches users attention (to indicate that the task was completed).
EDIT How to scale and rotate a view in a single animation
You might need use Core Animation and add both animations in a group:
CABasicAnimation *stetchAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale.x"];
stetchAnimation.toValue = [NSNumber numberWithDouble:(someView.frame.size.width+100)/someView.frame.size.width];
CABasicAnimation *skewAnimation = CABasicAnimation animationWithKeyPath:#"transform.rotation.x"];
stetchAnimation.toValue:[NSNumber numberWithInt:180];
//Add both animation at time when task is completed
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = [NSArray arrayWithObjects:stetchAnimation,skewAnimation,nil];
animationGroup.removedOnCompletion = YES;
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.duration = 0.7; // increase duration if needed
[someView.layer addAnimation:animationGroup forKey:#"animations"];
Simple UIView animation; temporarily grows the view:
[UIView animateWithDuration:0.3 animations:^{
CGRect frm = view.frame;
frm.size.width += 20;
frm.size.height += 20;
frm.origin.x -= 10;
frm.origin.y -= 10;
view.frame = frm;
} completion:^{
[UIView animateWithDuration:0.3 animations:^{
CGRect frm = view.frame;
frm.size.width -= 20;
frm.size.height -= 20;
frm.origin.x += 10;
frm.origin.y += 10;
view.frame = frm;
}];
}];
Related
i face trouble to apply pendulum animation base gravity effect on my UIImageView. can any buddy help me to come out from this trouble??
i have tried below source code. but in that gravitational force is not apply.
- (void)swingPendulum {
pendulum.layer.anchorPoint = CGPointMake(0.5,0);
[pendulum.layer setTransform:CATransform3DMakeRotation(-M_PI*3/4, 0, 0, 1)];
CABasicAnimation *needleAnim = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
needleAnim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
needleAnim.duration = 1;
needleAnim.repeatCount = 5;
needleAnim.autoreverses = YES;
// Setting fillMode means that, once the animation finishes, the needle stays in its end position.
needleAnim.fillMode = kCAFillModeForwards;
needleAnim.removedOnCompletion = YES;
needleAnim.toValue = [NSNumber numberWithFloat:M_PI*3/4];
[pendulum.layer addAnimation:needleAnim forKey:nil];
}
actually we need animation like...
check out this : http://blog.ruben-martins.co.uk/2010/02/maya-tutorials-pendulum-animation.html
Thanks in Advance.
If you've got an image with a blank top section and starts in the middle and just want to rotate it (haven't tried it tho):
-(void) doAnimation {
imgView.transform = CGAffineTransformMakeRotation(-0.7);
[UIView animateWithDuration:4 delay:0 options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAutoreverse animations:^{
imgView.transform = CGAffineTransformMakeRotation(0.7);
} completion:^{
[self doAnimation];
}]
I find at least 5 other "UIView animation doesn't work" questions, I hate to add yet another one. :(. I'm sure this isn't something specific to alpha. Same issue with backgroundColor. So it is something basic.
This works:
[self.view viewWithTag:kPlayView].alpha = 0.75;
[self.view viewWithTag:kCancelView].alpha = 0.75;
[self.view viewWithTag:kTapViewTag].backgroundColor = [UIColor whiteColor];
This doesn't (it doesn't do anything):
//kPlayView and kCancelView are subviews of kTapViewTag
[UIView animateWithDuration:2.0 animations:^{
[self.view viewWithTag:kPlayView].alpha = 0.75;
[self.view viewWithTag:kCancelView].alpha = 0.75;
[self.view viewWithTag:kTapViewTag].backgroundColor = [UIColor whiteColor];
} ];
Why? This is called in the gesture handler for the kTapViewTag view. It is view with backgorundColor = [UIColor clearColor] that I want to fade to white and change alpha of subviews to 0.75 in response to tap gesture.
UPDATE:
The reverse works. This works:
[UIView animateWithDuration:2.0 animations:^{
[self.view viewWithTag:kPlayView].alpha = 0;
[self.view viewWithTag:kCancelView].alpha = 0;
[self.view viewWithTag:kTapViewTag].backgroundColor = [UIColor clearColor];
}];
I am able to show the view that acts as a "pause/resume" without animation, and then animate the fade out. This works back and forth as long as I don't try to animate the fade in.
UPDATE 2
Here is the entire implementation for reference. Something in here? (I've looked too many times).
- (void)didTap:(id)selector
{
isPaused = (isPaused) ? NO: YES;
[self.view viewWithTag:kPlayView].userInteractionEnabled = isPaused;
[self.view viewWithTag:kCancelView].userInteractionEnabled = isPaused;
if (isPaused)
{
[self pauseLayer:self.view.layer];
[timer1 invalidate];
[timer2 invalidate];
[UIView animateWithDuration:2.0 animations:^{
[self.view viewWithTag:kPlayView].alpha = 0.75;
[self.view viewWithTag:kCancelView].alpha = 0.75;
[self.view viewWithTag:kTapViewTag].backgroundColor = [UIColor whiteColor];
} ];
}
else
{
isPaused = NO;
[UIView animateWithDuration:2.0 animations:^{
[self.view viewWithTag:kPlayView].alpha = 0;
[self.view viewWithTag:kCancelView].alpha = 0;
[self.view viewWithTag:kTapViewTag].backgroundColor = [UIColor clearColor];
}];
[self resumeLayer:self.view.layer];
[self animateNotification];
}
}
UPDATE 3
- (void)pauseLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;
}
- (void)resumeLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}
UIView animations are a nice high level wrapper around Core Animation, which renders its animations using your view's layer. By setting the layer speed to 0 you effectively are stopping the uiview animations from starting.
When you start the layer time again you start it from exactly where it left off. The animations from before you paused and after are coalesced and nothing happens.
The reason the animations work in the other direction when you don't animate in is because of the way the animations are set up and fired. When you call [UIView animate... it sets up a low level animation on the layer with a begin time and an end time and so on. The code you write completes instantly and the animation would begin on the next go of the runloop. Before you let everything return, however you also resume the layer's time and speed and so when it comes to do the animation everything proceeds as normal.
My guess is you don't mean to suspend the layer like this. There must be better ways of removing and stopping your animations. e.g. with UIView you just animate the property again and it stops, with CALayer you have removeAllAnimations and removeAnimationForKey: and also you can look into using -[CALayer presentationLayer] to find out where a particular layer is on screen at a particular point in an animation and then adjust the actual layer values to match.
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"
Given:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:.5];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:card cache:NO];
myPic = [UIImage UIImagenamed: #"mySecondImage.png"];
[UIView commitAnimations];[/CODE]
Which animates 'myPic' right to left with a flip.
I need to get the same animation, but vertically. Flip from Top or Flip from Bottom. I looked around, no one really had a working model suggested.
I tried this, yet, no luck:
float duration = .5;
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.x"];
animation.fromValue = [NSNumber numberWithDouble:0.0f * M_PI];
animation.toValue = [NSNumber numberWithDouble:1.0f * M_PI];
animation.duration = duration;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeBoth;
animation.repeatCount =1;;
animation.beginTime = CACurrentMediaTime();
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
card.layer.anchorPoint = CGPointMake(0.5, 1.0);
[card.layer addAnimation:animation forKey:#"rotationX"];[/CODE]
Any input?
Thanks in advance.
I've also needed flip from bottom animation. I've compiled couple solutions and this works for me
- (CATransform3D) makeRotationAndPerspectiveTransform:(CGFloat) angle {
CATransform3D transform = CATransform3DMakeRotation(angle, 1.0f, 0.0f, 0.0f);
transform.m34 = 1.0 / -500;
return transform;
}
- (void) flipFromBottom {
//setup firstView to be visible
view1.layer.transform = CATransform3DMakeRotation(0, 1.0f, 0.0f, 0.0f);
view1.hidden = NO;
// setup secondView to be partialy rotated and invisible
view2.layer.transform = [self makeRotationAndPerspectiveTransform:M_PI/2];
view2.hidden = YES;
// making sure that both views have the same position
view2.frame = view1.frame;
CFTimeInterval duration = 2.0;
[UIView animateWithDuration:duration/2
delay:0
options:UIViewAnimationCurveEaseIn
animations:^{
view1.layer.transform = [self makeRotationAndPerspectiveTransform:-M_PI / 2];
}
completion:^(BOOL finished){
view1.hidden = YES;
view2.hidden = NO;
[UIView animateWithDuration:duration /2
delay:0
options:UIViewAnimationCurveEaseOut
animations:^{
view2.layer.transform = CATransform3DMakeRotation(0.0f, 1.0f, 0.0f, 0.0f);
}
completion:NULL];
}];
}
I'd like to "Stretch" a UIView to the right side, meaning increase it's frame.size.width by foo pixels and at the same time decreasing it's frame.origin.x by foo pixels, using [UIView beginAnimations] syntax.
However, if I do that, when the animation begins the view immediately resizes, and then starts the animation for the origin.
CGRect currFrame = someView.frame;
currFrame.size.width += 100;
currFrame.origin.x -= 100;
[UIView beginAnimations:#"Anim1" context:nil];
someView.frame = currFrame;
[UIView setAnimationDuration:0.7];
[UIView commitAnimations];
I've also tried breaking the animation down to 2 parts but then I can't keep the right position in place.
Any help is much appreciated!
You might need to drop down to Core Animation and break this into two explicit animations:
CABasicAnimation *stetchAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale.x"];
stetchAnimation.toValue = [NSNumber numberWithDouble:(someView.frame.size.width+100)/someView.frame.size.width];
CABasicAnimation *slideAnimation = [CABasicAnimation animationWithKeyPath:#"transform.translation.x"];
slideAnimation.toValue = [NSNumber numberWithDouble:-100];
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = [NSArray arrayWithObjects:stetchAnimation,slideAnimation,nil];
animationGroup.removedOnCompletion = NO;
animationGroup.fillMode = kCAFillModeForwards;
animationGroup.duration = 0.7;
[someView.layer addAnimation:animationGroup forKey:#"animations"];