Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subclassing UIButton and overriding touch events - not working

I need a scale spring animation for all my buttons in a project. So i subclassed UIButton and override touch event functions.

import UIKit

class UIAnimatedButton: UIButton {

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {

    UIView.animateWithDuration(0.1, animations: { () -> Void in
        self.transform = CGAffineTransformMakeScale(0.8, 0.8)

    })
    super.touchesBegan(touches, withEvent: event)

}

override func touchesCancelled(touches: Set<NSObject>!, withEvent event: UIEvent!) {


    UIView.animateWithDuration(0.5,
        delay: 0,
        usingSpringWithDamping: 0.2,
        initialSpringVelocity: 6.0,
        options: UIViewAnimationOptions.AllowUserInteraction,
        animations: { () -> Void in
            self.transform = CGAffineTransformIdentity
    }) { (Bool) -> Void in
        super.touchesCancelled(touches, withEvent: event)
    }

}


override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {

    UIView.animateWithDuration(0.5,
        delay: 0,
        usingSpringWithDamping: 0.2,
        initialSpringVelocity: 6.0,
        options: UIViewAnimationOptions.AllowUserInteraction,
        animations: { () -> Void in
            self.transform = CGAffineTransformIdentity
        }) { (Bool) -> Void in
            super.touchesEnded(touches, withEvent: event)
    }
  }
} 

this works great in a fast tap but when i touch the button for a long time (1-2 seconds) i don't get a touch up inside action event. when i switch it back to a regular UIButton everything works fine.

Any ideas why that happens?

like image 301
ilan Avatar asked Jun 28 '15 21:06

ilan


2 Answers

Instead of calling super in the completion block of touchesCancelled and touchesEnded methods I called self.sendActionsForControlEvents(UIControlEvents.TouchUpInside) in there.

like image 194
ilan Avatar answered Sep 20 '22 21:09

ilan


Not sure exactly why yet, but you need to call super.touchesEnded(touches, with: event) outside the animation

So (Swift 5)

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    UIView.animate(withDuration: 0.5,
        delay: 0,
        usingSpringWithDamping: 0.2,
        initialSpringVelocity: 6.0,
        options: UIView.AnimationOptions.allowUserInteraction,
        animations: { () -> Void in
            self.transform = CGAffineTransform.identity
        }) { (Bool) -> Void in
    }
    super.touchesEnded(touches, with: event)
}
like image 34
Arnaud Avatar answered Sep 20 '22 21:09

Arnaud