UIView Animation Animation

I am trying to shake a UIView when a button is clicked.

I am adapting the code that I found at http://www.cimgf.com/2008/02/27/core-animation-tutorial-window-shake-effect/ .

However, trying to adapt the following code to shake UIView, it does not work:

- (void)animate { const int numberOfShakes = 8; const float durationOfShake = 0.5f; const float vigourOfShake = 0.1f; CAKeyframeAnimation *shakeAnimation = [CAKeyframeAnimation animation]; CGRect frame = lockView.frame; CGMutablePathRef shakePath = CGPathCreateMutable(); CGPathMoveToPoint(shakePath, NULL, CGRectGetMinX(frame), CGRectGetMinY(frame)); for (int index = 0; index < numberOfShakes; ++index) { CGPathAddLineToPoint(shakePath, NULL, CGRectGetMinX(frame) - frame.size.width * vigourOfShake, CGRectGetMinY(frame)); CGPathAddLineToPoint(shakePath, NULL, CGRectGetMinX(frame) + frame.size.width * vigourOfShake, CGRectGetMinY(frame)); } CGPathCloseSubpath(shakePath); shakeAnimation.path = shakePath; shakeAnimation.duration = durationOfShake; [lockView.layer addAnimation:shakeAnimation forKey:@"frameOrigin"]; } 
+77
ios iphone cocoa-touch animation core-animation
Oct 02 '10 at 5:52
source share
17 answers

I wrote this post. This is redundant for UIView, plus the options are OSX-oriented. Do it instead.

 CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"]; [animation setDuration:0.05]; [animation setRepeatCount:8]; [animation setAutoreverses:YES]; [animation setFromValue:[NSValue valueWithCGPoint: CGPointMake([lockView center].x - 20.0f, [lockView center].y)]]; [animation setToValue:[NSValue valueWithCGPoint: CGPointMake([lockView center].x + 20.0f, [lockView center].y)]]; [[lockView layer] addAnimation:animation forKey:@"position"]; 

You will have to play with the duration and repeatCount parameters, as well as the distance x from the center in the from and to values, but it should give you what you need. Hope this helps. Let me know if you have any questions.

---




Swift 3.0

 let midX = lockView.center.x let midY = lockView.center.y let animation = CABasicAnimation(keyPath: "position") animation.duration = 0.06 animation.repeatCount = 4 animation.autoreverses = true animation.fromValue = CGPoint(x: midX - 10, y: midY) animation.toValue = CGPoint(x: midX + 10, y: midY) layer.add(animation, forKey: "position") 
+194
04 Oct 2018-10-18
source share

I prefer this solution, which has nice resilient behavior, perfect for animating jitter with the wrong password.

 view.transform = CGAffineTransformMakeTranslation(20, 0); [UIView animateWithDuration:0.4 delay:0.0 usingSpringWithDamping:0.2 initialSpringVelocity:1.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ view.transform = CGAffineTransformIdentity; } completion:nil]; 

Swift 3

 extension UIView { func shake() { self.transform = CGAffineTransform(translationX: 20, y: 0) UIView.animate(withDuration: 0.4, delay: 0, usingSpringWithDamping: 0.2, initialSpringVelocity: 1, options: .curveEaseInOut, animations: { self.transform = CGAffineTransform.identity }, completion: nil) } } 
+70
01 Oct '15 at 14:34
source share

Here is my nice and simple version. This mimics the shaking you get on Mac OS X when you make a mistake. You can add this as a category in a UIView if you want.

 @implementation UIView (DUExtensions) - (void) shake { CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"transform.translation.x"]; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; animation.duration = 0.6; animation.values = @[ @(-20), @(20), @(-20), @(20), @(-10), @(10), @(-5), @(5), @(0) ]; [self.layer addAnimation:animation forKey:@"shake"]; } @end 

Animation values ​​represent the x offset from the current view position. Positive values ​​move the view to the right, and negative values ​​shift it to the left. By gradually reducing them, you get a shiver that naturally loses momentum. You can customize these numbers if you wish.

+32
Jun 27 '13 at 20:19
source share

Here is the quick version as an extension, if someone needs it

 extension UIImageView{ func vibrate(){ let animation = CABasicAnimation(keyPath: "position") animation.duration = 0.05 animation.repeatCount = 5 animation.autoreverses = true animation.fromValue = NSValue(CGPoint: CGPointMake(self.center.x - 2.0, self.center.y)) animation.toValue = NSValue(CGPoint: CGPointMake(self.center.x + 2.0, self.center.y)) self.layer.addAnimation(animation, forKey: "position") } } 

This will animate a small UIImageView (about 15x15). If you need to animate something more, you might want to change the coefficient 2.0 to move to something more.

+15
May 8 '15 at 4:36
source share

Based on @bandejapaisa answer, UIView extension for Swift 3

 extension UIView { func shake() { let animation = CAKeyframeAnimation(keyPath: "transform.translation.x") animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) animation.duration = 0.6 animation.values = [-20, 20, -20, 20, -10, 10, -5, 5, 0] layer.addAnimation(animation, forKey: "shake") } } 
+8
May 12 '16 at 15:14
source share
+6
Jan 23 2018-11-21T00:
source share

You can try this piece of code:

to call the code below, use: [self earthquake:myObject];

 #pragma mark EarthQuake Methods - (void)earthquake:(UIView*)itemView { AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); CGFloat t = 2.0; CGAffineTransform leftQuake = CGAffineTransformTranslate(CGAffineTransformIdentity, t, -t); CGAffineTransform rightQuake = CGAffineTransformTranslate(CGAffineTransformIdentity, -t, t); itemView.transform = leftQuake; // starting point [UIView beginAnimations:@"earthquake" context:itemView]; [UIView setAnimationRepeatAutoreverses:YES]; // important [UIView setAnimationRepeatCount:3]; [UIView setAnimationDuration:0.05]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(earthquakeEnded:finished:context:)]; itemView.transform = rightQuake; // end here & auto-reverse [UIView commitAnimations]; } - (void)earthquakeEnded:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { if ([finished boolValue]) { UIView* item = (UIView *)context; item.transform = CGAffineTransformIdentity; } } 
+4
Jan 23 2018-11-21T00:
source share

You can call this method on a UIButton click event

 -(void)shakescreen { //Shake screen CGFloat t = 5.0; CGAffineTransform translateRight = CGAffineTransformTranslate(CGAffineTransformIdentity, t, t); CGAffineTransform translateLeft = CGAffineTransformTranslate(CGAffineTransformIdentity, -t, -t); self.view.transform = translateLeft; [UIView animateWithDuration:0.05 delay:0.0 options:UIViewAnimationOptionAutoreverse|UIViewAnimationOptionRepeat animations:^ { [UIView setAnimationRepeatCount:2.0]; self.view.transform = translateRight; } completion:^(BOOL finished) { if (finished) { [UIView animateWithDuration:0.05 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^ { self.view.transform = CGAffineTransformIdentity; } completion:NULL]; } }]; } 

Hope this helps you :-)

+4
Mar 29 '12 at 6:00
source share

C # version of Xamarin.iOS answer how to create shake UIView animation in iOS below

  CAKeyFrameAnimation keyframeAnimation = CAKeyFrameAnimation.GetFromKeyPath(new NSString("transform.translation.x")); keyframeAnimation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut); keyframeAnimation.Duration = 0.6f; keyframeAnimation.Values = new NSObject[]{ new NSNumber(-20f), new NSNumber(20f), new NSNumber(-20f), new NSNumber(20f), new NSNumber(-10f), new NSNumber(10f), new NSNumber(-5f), new NSNumber(5f), new NSNumber(0f) }; shakyView.Layer.AddAnimation(keyframeAnimation, "shake"); 
+3
Dec 27 '14 at 7:15
source share

The damper function is used here to break out the shiver:

 - (void)shake { CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"position"]; animation.duration = 0.5; animation.delegate = self; animation.fillMode = kCAFillModeForwards; animation.removedOnCompletion = YES; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; NSMutableArray* values = [[NSMutableArray alloc] init]; int steps = 100; double position = 0; float e = 2.71; for (int t = 0; t < steps; t++) { position = 10 * pow(e, -0.022 * t) * sin(0.12 * t); NSValue* value = [NSValue valueWithCGPoint:CGPointMake([self center].x - position, [self center].y)]; DDLogInfo(@"Value: %@", value); [values addObject:value]; } animation.values = values; [[self layer] addAnimation:animation forKey:@"position"]; } 
+2
Jun 12 '13 at 9:11
source share

Swift 3 implementation based on @ Mihael-Isaev's answer

 private enum Axis: StringLiteralType { case x = "x" case y = "y" } extension UIView { private func shake(on axis: Axis) { let animation = CAKeyframeAnimation(keyPath: "transform.translation.\(axis.rawValue)") animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) animation.duration = 0.6 animation.values = [-20, 20, -20, 20, -10, 10, -5, 5, 0] layer.add(animation, forKey: "shake") } func shakeOnXAxis() { self.shake(on: .x) } func shakeOnYAxis() { self.shake(on: .y) } } 
+2
Oct 26 '16 at 17:43
source share

You can try the following code:

 + (void)vibrateView:(UIView*)view { CABasicAnimation *shiverAnimationR; shiverAnimationR = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; shiverAnimationR.toValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(1)]; //shiverAnimationR.toValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(-10)]; shiverAnimationR.duration = 0.1; shiverAnimationR.repeatCount = 1000000.0; // Use A high Value shiverAnimationR.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; [view.layer addAnimation: shiverAnimationR forKey:@"shiverAnimationR"]; CABasicAnimation * shiverAnimationL; shiverAnimationL = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"]; //shiverAnimationL 2.toValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(10)]; shiverAnimationL.toValue = [NSNumber numberWithFloat:DEGREES_TO_RADIANS(-1)]; shiverAnimationL.duration = 0.1; shiverAnimationL.repeatCount = 1000000.0; shiverAnimationL.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]; [view.layer addAnimation: shiverAnimationL forKey:@"shiverAnimationL"]; } 

From the link.

+1
Oct 22 '13 at 15:31
source share

I reorganized @Matt long code and made a category before UIView . Now it is much more reusable and easy to use.

 @implementation UIView (Animation) - (void)shakeViewWithOffest:(CGFloat)offset { CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position.x"]; [animation setDuration:0.05]; [animation setRepeatCount:6]; [animation setAutoreverses:YES]; [animation setFromValue:@([self center].x-offset)]; [animation setToValue:@([self center].x+offset)]; [self.layer addAnimation:animation forKey:@"position.x"]; } - (void)shake { [self shakeViewWithOffest:7.0f]; } @end 
+1
Jul 21 '14 at 11:37
source share

Here is the version using

 + (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion 

Introduced in iOS 7.

  const CGFloat xDelta = 16.0f; [UIView animateKeyframesWithDuration:0.50f delay:0.0f options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{ [UIView addKeyframeWithRelativeStartTime:0.0 relativeDuration:(1.0/6.0) animations:^{ self.passwordTextField.transform = self.usernameTextField.transform = CGAffineTransformMakeTranslation(xDelta, 0.0); }]; [UIView addKeyframeWithRelativeStartTime:(1.0/6.0) relativeDuration:(1.0/6.0) animations:^{ self.passwordTextField.transform = self.usernameTextField.transform = CGAffineTransformMakeTranslation(-xDelta, 0.0); }]; [UIView addKeyframeWithRelativeStartTime:(1.0/3.0) relativeDuration:(1.0/3.0) animations:^{ self.passwordTextField.transform = self.usernameTextField.transform = CGAffineTransformMakeTranslation(xDelta/2.0, 0.0); }]; [UIView addKeyframeWithRelativeStartTime:(2.0/3.0) relativeDuration:(1.0/3.0) animations:^{ self.passwordTextField.transform = self.usernameTextField.transform = CGAffineTransformIdentity; }]; } completion:NULL]; 
+1
Jan 07 '15 at 15:06
source share

@imike answer in Swift 4.2

 extension UIView { func shake() { let animation = CAKeyframeAnimation(keyPath: "transform.translation.x") animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) animation.duration = 0.6 animation.values = [-20, 20, -20, 20, -10, 10, -5, 5, 0] self.layer.add(animation, forKey: "shake") }} 
+1
Jan 24 '19 at 5:32
source share

Here is the UIView extension providing awesome jitter animation: https://gist.github.com/mourad-brahim/cf0bfe9bec5f33a6ea66

The Swift5 update is provided in the comments.

0
Jul 02 '19 at 15:44
source share

Swift 4.0:

Based on the top answer, but animation is refined: there are no transitions at the beginning and end of the animation.

  let midX = center.x let midY = center.y let rightAnim = CABasicAnimation(keyPath: #keyPath(CALayer.position)) rightAnim.duration = 0.07 rightAnim.autoreverses = true rightAnim.fromValue = CGPoint(x: midX, y: midY) rightAnim.toValue = CGPoint(x: midX + 9, y: midY) let leftAnim = CABasicAnimation(keyPath: #keyPath(CALayer.position)) leftAnim.duration = 0.07 leftAnim.autoreverses = true leftAnim.fromValue = CGPoint(x: midX, y: midY) leftAnim.toValue = CGPoint(x: midX - 9, y: midY) let group = CAAnimationGroup() group.duration = leftAnim.duration + rightAnim.duration group.animations = [rightAnim, leftAnim] group.repeatCount = 3 layer.add(group, forKey: #keyPath(CALayer.position)) 
0
Aug 15 '19 at 3:12
source share



All Articles