i\'m trying to make a UIView shake when a button is pressed.
I am adapting the code I found on http://www.cimgf.com/2008/02/27/core-animation-tutorial-window-shake-e
Here is the swift version as an extension in case anybody 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 an small UIImageView (around 15x15). If you need to animate something bigger you may want to change the 2.0 factor of movement to something greater.
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;
}
}
Here is a UIView extension providing an awesome shake animation: https://gist.github.com/mourad-brahim/cf0bfe9bec5f33a6ea66
A Swift5 update is provided on the comments.
Here's one that uses a damper function to decay the shake:
- (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"];
}
You can call this method on 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 will help you :-)
C# Xamarin.iOS version of answer how to create UIView shake animation in iOS is 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");