Uiview Shake Animation

UIView shake animation

I wrote that post. It's overkill for a UIView, plus the parameters are geared toward an OSX app. Do this 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'll have to play with the duration and repeatCount parameters as well as the x distance from center in the from and to values, but it should give you what you need. I hope that 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")

Shake Animation for UITextField/UIView in Swift

You can change the duration and repeatCount and tweak it. This is what I use in my code. Varying the fromValue and toValue will vary the distance moved in the shake.

let animation = CABasicAnimation(keyPath: "position")
animation.duration = 0.07
animation.repeatCount = 4
animation.autoreverses = true
animation.fromValue = NSValue(cgPoint: CGPoint(x: viewToShake.center.x - 10, y: viewToShake.center.y))
animation.toValue = NSValue(cgPoint: CGPoint(x: viewToShake.center.x + 10, y: viewToShake.center.y))

viewToShake.layer.add(animation, forKey: "position")

How can i put shake Animation on UIImageView

You need

var coffeeImageView = UIImageView(image: UIImage(named: "coffee.png"))
coffeeImageView.frame = CGRect(x: 100, y: self.view.frame.size.height - 100, width: 50, height: 50)
self.view.addSubview(coffeeImageView)
let coffeeShakeAnimation = CABasicAnimation(keyPath: "position")
coffeeShakeAnimation.duration = 0.07
coffeeShakeAnimation.repeatCount = 20
coffeeShakeAnimation.autoreverses = true
coffeeShakeAnimation.fromValue = NSValue(cgPoint: CGPoint(x: coffeeImageView.center.x - 10, y: coffeeImageView.center.y))
coffeeShakeAnimation.toValue = NSValue(cgPoint: CGPoint(x: coffeeImageView.center.x + 10, y: coffeeImageView.center.y))
coffeeImageView.layer.add(coffeeShakeAnimation, forKey: "position")

extension UIView {
func shake(_ dur:Double) {
let anim = CABasicAnimation(keyPath: "position")
anim.duration = dur
anim.repeatCount = 20
anim.autoreverses = true
anim.fromValue = NSValue(cgPoint: CGPoint(x: self.center.x - 10, y: self.center.y))
anim.toValue = NSValue(cgPoint: CGPoint(x: self.center.x + 10, y: self.center.y))
self.layer.add(anim, forKey: "position")
}
}

Sample Image

How to make UIButton shake on tap?

Here is simple media timing animation for linear movement & UIView damping animation.

Sample Image

Note: Swift 4

extension UIView {


// Using CAMediaTimingFunction
func shake(duration: TimeInterval = 0.5, values: [CGFloat]) {
let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")

// Swift 4.2 and above
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)

// Swift 4.1 and below
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)


animation.duration = duration // You can set fix duration
animation.values = values // You can set fix values here also
self.layer.add(animation, forKey: "shake")
}


// Using SpringWithDamping
func shake(duration: TimeInterval = 0.5, xValue: CGFloat = 12, yValue: CGFloat = 0) {
self.transform = CGAffineTransform(translationX: xValue, y: yValue)
UIView.animate(withDuration: duration, delay: 0, usingSpringWithDamping: 0.4, initialSpringVelocity: 1.0, options: .curveEaseInOut, animations: {
self.transform = CGAffineTransform.identity
}, completion: nil)

}


// Using CABasicAnimation
func shake(duration: TimeInterval = 0.05, shakeCount: Float = 6, xValue: CGFloat = 12, yValue: CGFloat = 0){
let animation = CABasicAnimation(keyPath: "position")
animation.duration = duration
animation.repeatCount = shakeCount
animation.autoreverses = true
animation.fromValue = NSValue(cgPoint: CGPoint(x: self.center.x - xValue, y: self.center.y - yValue))
animation.toValue = NSValue(cgPoint: CGPoint(x: self.center.x + xValue, y: self.center.y - yValue))
self.layer.add(animation, forKey: "shake")
}

}

Button Action

@IBAction func noButtonPressed(button: UIButton) {

// for spring damping animation
//button.shake()


// for CAMediaTimingFunction
button.shake(duration: 0.5, values: [-12.0, 12.0, -12.0, 12.0, -6.0, 6.0, -3.0, 3.0, 0.0])

// for CABasicAnimation
//button.shake(shakeCount: 10)

}

View shake animation error when clicked

You can try this code. It should be helpful:

extension UIView {

func shakeByX() {
let animation = CABasicAnimation(keyPath: "position")
animation.duration = 0.07
animation.repeatCount = 3
animation.autoreverses = true
animation.fromValue = NSValue(cgPoint: CGPoint(x: self.center.x - 6, y: self.center.y))
animation.toValue = NSValue(cgPoint: CGPoint(x: self.center.x + 6, y: self.center.y))
self.layer.add(animation, forKey: "position")
}

func shakeByY() {
let animation = CABasicAnimation(keyPath: "position")
animation.duration = 0.07
animation.repeatCount = 3
animation.autoreverses = true
animation.fromValue = NSValue(cgPoint: CGPoint(x: self.center.x, y: self.center.y - 6))
animation.toValue = NSValue(cgPoint: CGPoint(x: self.center.x, y: self.center.y + 6))
self.layer.add(animation, forKey: "position")
}
}

How to make shaking animation

Here's the code I use for that effect.

 -(void)shakeView {

CABasicAnimation *shake = [CABasicAnimation animationWithKeyPath:@"position"];
[shake setDuration:0.1];
[shake setRepeatCount:2];
[shake setAutoreverses:YES];
[shake setFromValue:[NSValue valueWithCGPoint:
CGPointMake(lockImage.center.x - 5,lockImage.center.y)]];
[shake setToValue:[NSValue valueWithCGPoint:
CGPointMake(lockImage.center.x + 5, lockImage.center.y)]];
[lockImage.layer addAnimation:shake forKey:@"position"];
}

As Jere mentioned. Make sure to include the import:

#import <QuartzCore/QuartzCore.h>

You can also add it as a category on UIView.

How do you make a shake animation for a button using Swift 3

if I understood you correctly, try this on shake animation.
Simply use this method in your UIButton subclass

class CustomButton: UIButton {

func shake() {
let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.duration = 0.6
animation.values = [-20.0, 20.0, -20.0, 20.0, -10.0, 10.0, -5.0, 5.0, 0.0 ]
layer.add(animation, forKey: "shake")
}
}

Then you create CustomButton somewhere in code or storyboard/xib and call myButton.shake()

You can simply adopt this solution on your needs

UPD: I have edit example than exactly fitted your needs

UPD2: another one solution
Just create UIButton extension

extension UIButton {

func shake() {
let animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.duration = 0.6
animation.values = [-20.0, 20.0, -20.0, 20.0, -10.0, 10.0, -5.0, 5.0, 0.0 ]
layer.add(animation, forKey: "shake")
}

}

ans use on you button action callback:

@IBAction func shake(_ sender: UIButton) {
sender.shake()
}

Shake animation rotating display as well as animating

The issue is that the view has a non identity transform on it already. In order for a view to display properly in landscape, the system applies a transform on it that rotates the view. The transform of the view is CGAffineTransformIdentity ONLY when the device is in UIDeviceOrientationPortrait. This orientation rotation ONLY applies to the root child of the application, the first subview of the window. When you are initializing your translation animation with:

CGAffineTransform translateRight = CGAffineTransformTranslate(CGAffineTransformIdentity, 0.0, t);

You are telling the rotated view to ignore its rotation and snap back to its orientation in portrait mode. You can solve this issue by doing one of two things:

  1. Make the animated view a subview of the root view. This has the advantage that the system will still handle rotations for free, and there isn't any chance that your animation will screw up the the orientation changes. Furthermore, the code will be simpler and easier to maintain in the end.

  2. Store the initial transformation of the view, and apply all transformations to it.

I'll try to do #2 here.

- (void)shakeView
{
CGFloat t = 8.0;

//store the initial transform and use it to create the animated transforms
CGAffineTransform initialTransform = self.view.transform;
CGAffineTransform translateRight = CGAffineTransformTranslate(initialTransform, 0.0, t);
CGAffineTransform translateLeft = CGAffineTransformTranslate(initialTransform, 0.0, -t);

self.view.transform = translateLeft;

[UIView animateWithDuration:0.07
delay:0.0
options:UIViewAnimationOptionAutoreverse|UIViewAnimationOptionRepeat
animations:^{
[UIView setAnimationRepeatCount:3.0];

self.view.transform = translateRight;
}
completion:^(BOOL finished){
if (finished)
{
[UIView animateWithDuration:0.05
delay:0.0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
//restore the initial transform
self.view.transform = initialTransform;
}
completion:NULL];
}
}];
}

Note - As of iOS 8, the root view of the UIWindow is no longer transformed on rotation. Instead the bounds of the UIWindow itself changes. For another question about this, see here: UIWindow frame in ios 8 different from ios 7 in Landscape



Related Topics



Leave a reply



Submit