Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make UIButton shake on tap? [duplicate]

I'm learning about UIView animations using keyframes and spring animations and I'm trying to make a button shake after tapping it. The issue is that I drag and dropped the button from the library and pinned the trailing edge to a UILabel above it and nothing else. In the various examples I see a header constraint but my button has no header. This is the code I have so far

@IBAction func noButtonPressed(_ sender: UIButton) {
    UIView.animate(withDuration: 1, delay: 1, usingSpringWithDamping: 0.5, initialSpringVelocity: 15, options: [], animations: {
        self.noButtonTrailing.constant = 16
        self.view.layoutIfNeeded()
    })
}

Am I suppose to make a header constraint somewhere? Thanks

like image 909
LampPost Avatar asked Oct 04 '17 03:10

LampPost


People also ask

How to create a new UIButton programmatically?

To create a new UIButton, set its width, height, and position the button within a view programmatically, you can do with CGRect class. For example: Setting text on a button is very simple. It can be done with a function call setTitle (_ title: String?, for state: UIControl.State) . A title on the button can be set for different button states.

How to create a new UIButton in Swift?

A new UIButton can be created of different types: ButtonType. close. To create a regular, system type button in Swift you will need to create a new instance of UIButton class. To create a button of a different type like for example ButtonType. close, you will do:

What are the different types of UIButton?

A new UIButton can be created of different types: 1 ButtonType. custom, 2 ButtonType. system, 3 ButtonType. detailDisclosure, 4 ButtonType. infoLight, 5 ButtonType. infoDark, 6 ButtonType. contactAdd, 7 ButtonType. close.

How do I use the repeated tap tool on my keyboard?

Basically, place the repeated tap spot anywhere on the screen, assign a key, and use that key to make more than one clicks with a single keystroke. With the latest update, the repeated tap tool gained one more feature: Long Press.


2 Answers

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

enter image description here

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)  

}
like image 157
Krunal Avatar answered Nov 14 '22 22:11

Krunal


Here is the output for @Krunal code. I used 3 different cases and output is pretty nice :)

Tests

    @IBAction func instagramButtonClicked(_ sender: Any) {
        guard let button = sender as? UIButton else {
            return
        }

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

    }

    @IBAction func facebookButtonClicked(_ sender: Any) {
        guard let button = sender as? UIButton else {
            return
        }

        button.shake()
    }
    @IBAction func websiteButtonClicked(_ sender: Any) {
        guard let button = sender as? UIButton else {
            return
        }

        button.shake(duration: 0.5, values: [-1.0, 1.0, -6.0, 6.0, -10.0, 10.0, -12.0, 12.0])

    }
like image 29
Siyavash Avatar answered Nov 14 '22 21:11

Siyavash