Search code examples
iosswiftanimationuibuttontouchesbegan

Animation not working on touchesBegan button highlight


I'm trying to highlight buttons using a custom UIImageView layer on top of the buttons, invoking touchesBegan, but its not animating.

It's working perfectly except I can't seem to get it to animate the highlighting, I made similar code for collectionView, using didHighlightItemAt which animates properly, what am I doing wrong in the case of button or what's the workaround here?

// For btn highlight
    func highlight(isHighlighted: Bool) {
        UIView.animate(withDuration: 0.08, delay: 0, options: [.allowUserInteraction, .overrideInheritedOptions, .curveEaseOut], animations: {
            let color = isHighlighted ? UIColor.black.withAlphaComponent(0.5) : .clear
            self.highlightBtn?.image = color.image()
            self.highlightBtn?.layer.compositingFilter = "softLightBlendMode"
        })
    }
    
    @IBAction func touchBeganButton(_ sender: UIButton) {
        highlight(isHighlighted: true)
        btnFollow.layer.borderWidth = 1.8
    }
    
    @IBAction func touchEndedButton(_ sender: UIButton) {
        highlight(isHighlighted: false)
        btnFollow.layer.borderWidth = 1.5
    }
    
    @IBAction func touchCancelButton(_ sender: UIButton) {
        highlight(isHighlighted: false)
        btnFollow.layer.borderWidth = 1.5
    }

I tried highlighting with a class (code below) but buttons can be of different colors depending on the API call, so it has to be a darkening effect of the same color, that's why I'm using an ImageView.

@IBDesignable
class HighlightButton: UIButton {
    
    @IBInspectable var normalBackgroundColor: UIColor? {
        didSet {
            backgroundColor = normalBackgroundColor
        }
    }
    
    @IBInspectable var highlightedBackgroundColor: UIColor?
    
    override var isHighlighted: Bool {
        didSet {
            if oldValue == false && isHighlighted {
                highlight()
            } else if oldValue == true && !isHighlighted {
                unHighlight()
            }
        }
    }
    
    var highlightDuration: TimeInterval = 0.08

    private func animateBackground(to color: UIColor?, duration: TimeInterval) {
        guard let color = color else { return }
        UIView.animate(withDuration: highlightDuration) {
            self.backgroundColor = color
        }
    }

    func highlight() {
        animateBackground(to: highlightedBackgroundColor, duration: highlightDuration)
    }

    func unHighlight() {
        animateBackground(to: normalBackgroundColor, duration: highlightDuration)
    } 
}

Any help is appreciated, Thanks.


Solution

  • So I figured out what I was doing wrong: I was trying to switch color of the image but the image itself would be attached in an instant, so what I really should've been doing is animating the alpha of the attached image, as follows:

    let color = UIColor.black.withAlphaComponent(0.5)
    self.highlightBtn?.image = color.image()
    self.highlightBtn?.alpha = isHighlighted ? 1 : 0
    self.highlightBtn?.layer.compositingFilter = "softLightBlendMode"