简体   繁体   中英

Tap Gesture not working when button is having animation & gradient masking

i want to add gradient to button title and also button should have animation like flashing/blinking. By adding this, tap gesture is not working

i have created a view named 'maskingView' and button is inside that view named 'btnGradient' using storyboard

    let gradient = CAGradientLayer()
    gradient.colors = [UIColor.red.cgColor, UIColor.blue.cgColor]
    gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
    gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
    gradient.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 30)
    maskingView = btnGradient

    // function for animation
    blinkAnimation()

    let tap = UITapGestureRecognizer(target: self, action: #selector(self.goToOtherView(gesture:)))
    tap.delegate = self
    tap.numberOfTapsRequired = 1
    self. maskingView.isUserInteractionEnabled = true
    self. maskingView.addGestureRecognizer(tap)
    maskingView.layer.insertSublayer(gradient, at: 0)


    func blinkAnimation(){
    maskingView.alpha = 1.0
    UIView.animate(withDuration: 0.5, delay: 0.0, options: [.repeat, .autoreverse, .allowUserInteraction], animations: {
        self.maskingView.alpha = 0.0
    }, completion: nil)
    }

This is not working because you're setting self.maskingView.alpha = 0.0 . If you are set alpha to 0 then the system considers it as a hidden view! Once try by setting alpha-like,

self.maskingView.alpha = 0.1

Sample Code:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var maskingView: UIView!
    override func viewDidLoad() {
        super.viewDidLoad()

        let gradient = CAGradientLayer()
        gradient.colors = [UIColor.red.cgColor, UIColor.blue.cgColor]
        gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
        gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
        gradient.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 30)

        // function for animation
        blinkAnimation()

        let tap = UITapGestureRecognizer(target: self, action: #selector(self.goToOtherView(gesture:)))
        tap.numberOfTapsRequired = 1
        self.maskingView.isUserInteractionEnabled = true
        self.maskingView.addGestureRecognizer(tap)
        maskingView.layer.insertSublayer(gradient, at: 0)

        // Do any additional setup after loading the view.
    }

    func blinkAnimation(){
        maskingView.alpha = 1.0
        UIView.animate(withDuration: 0.5, delay: 0.0, options: [.repeat, .autoreverse, .allowUserInteraction], animations: {
            self.maskingView.alpha = 0.1
        }, completion: nil)
    }

    @objc func goToOtherView(gesture:Any) {
        print("tap")
    }
}

Apple describe in it's Animation docs:

"In iOS, animations are used extensively to reposition views, change their size, remove them from view hierarchies, and hide them."

View Programming Guide - Apple

The article continues with a fairly strong emphasis on using Core Animations rather than UIView Animations for more detailed animations.

"In places where you want to perform more sophisticated animations, or animations not supported by the UIView class, you can use Core Animation and the view's underlying layer to create the animation. Because view and layer objects are intricately linked together, changes to a view's layer affect the view itself."

So basically put, you manipulate the view's layer to change the view. I don't think it wise to manipulate the view directly when Core Animations exist for this purpose. So, you can't (and probably shouldn't) do to the UIView with UIAnimations what you can do to the Layer with Core Animations.

You have to do animation with CoreAnimation . Hence your blinkAnimation() Method will be,

func blinkAnimation(){
    let fadein = CABasicAnimation(keyPath: "opacity")
    fadein.fromValue = 1.0
    fadein.toValue = 0.0
    fadein.duration = 0.5
    fadein.autoreverses = true
    fadein.repeatCount = HUGE
    maskingView.layer.add(fadein, forKey: "opacity")
}

Here is full Code,

    let gradient = CAGradientLayer()
    gradient.colors = [UIColor.red.cgColor, UIColor.blue.cgColor]
    gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
    gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
    gradient.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 30)
    maskingView = btnGradient

    // function for animation
    blinkAnimation()

    let tap = UITapGestureRecognizer(target: self, action: #selector(self.goToOtherView(gesture:)))
    tap.delegate = self as! UIGestureRecognizerDelegate
    tap.numberOfTapsRequired = 1
    self.maskingView.isUserInteractionEnabled = true
    self.maskingView.addGestureRecognizer(tap)
    maskingView.layer.insertSublayer(gradient, at: 0)

Tap Gesture Selector Method is,

@objc func goToOtherView(gesture: UITapGestureRecognizer) {
        print("tap gesture selector called")
    }

masking, animation & tapGesture/button click(touchUpInside) does not work at the same time

so in order to add gradient use

btnGradient.setTitleColor(UIColor(patternImage: UIImage(named: "gradientImage")!), for: .normal)

now add animation and use use touchUpInside event on button

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM