首页 > 解决方案 > 如何在动画中设置带有图像的 UIButton?

问题描述

出于某种原因,我的动画没有等待 10 秒来执行。一旦我将手指从按钮上抬起并且按钮没有红色动画,它就会执行。

    SomeClass: UIViewController {


    override func viewDidLoad() {
    super.viewDidLoad()

    tapBeatButton.addTarget(self, action: #selector(tapBeatButtonTouchedDown), for: UIControl.Event.touchDown)
    tapBeatButton.addTarget(self, action: #selector(tapBeatButtonTouchedUpInside), for: UIControl.Event.touchUpInside)
     }

     @objc func tapBeatButtonTouchedDown() {

    print("it's red")

    //keep it red for 10 seconds, then make it blue

    UIView.animate(withDuration: 10.0, animations: {
       // it does not wait 10 seconds. It executes immediately

        self.tapBeatButton.setImage(#imageLiteral(resourceName: "icon-beat-selected"), for: .normal)

    },completion: { _ in
         self.tapBeatButton.setImage(#imageLiteral(resourceName: "icon-beat-unselected"), for: .normal)
        print("out")
    })

}

       @objc func tapBeatButtonTouchedUpInside() {
         print("it's blue    ")
         tapBeatButton.setImage(#imageLiteral(resourceName: "icon-beat-unselected"), for: .normal)
      }

  }//end class

标签: swiftuiviewanimation

解决方案


对于这种行为,您最好将您的 UIButton 子类化。

class MyImageButton: UIButton {

    private var firstImage: UIImageView = {
        let iv = UIImageView()
        iv.image = UIImage(named: "my_image_1")
        iv.contentMode = .center
        iv.translatesAutoresizingMaskIntoConstraints = false
        iv.heightAnchor.constraint(equalToConstant: 48.0).isActive = true
        iv.widthAnchor.constraint(equalToConstant: 48.0).isActive = true
        return iv
    }()

    private var secondImage: UIImageView = {
        let iv = UIImageView()
        iv.image = UIImage(named: "my_image_2")
        iv.contentMode = .center
        iv.translatesAutoresizingMaskIntoConstraints = false
        iv.heightAnchor.constraint(equalToConstant: 48.0).isActive = true
        iv.widthAnchor.constraint(equalToConstant: 48.0).isActive = true
        // this one starts invisible
        iv.alpha = 0.0
        return iv
    }()


    init() {
        super.init(frame: CGRect())
        // Hard coding height and width here. Feel free to set using frame instead.
        self.translatesAutoresizingMaskIntoConstraints = false
        self.heightAnchor.constraint(equalToConstant: 56.0).isActive = true
        self.widthAnchor.constraint(equalToConstant: 56.0).isActive = true

        self.addSubview(firstImage)
        firstImage.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
        firstImage.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true

        self.addSubview(secondImage)
        secondImage.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
        secondImage.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

   public func transitionImages() {
       // Swap which image is visible by setting them to be the opposite alpha values. Transition for 1 second.
       UIView.animate(withDuration: 1.0) {
           self.firstImage.alpha = self.firstImage.alpha == 0.0 ? 1.0 : 0.0
           self.secondImage.alpha = self.secondImage.alpha == 0.0 ? 1.0 : 0.0
       }
   }

}


然后在你的 viewController 中:

class MyViewController: UIViewController {

    override func viewDidLoad() {
        let mybutton = MyImageButton()
        mybutton.addTarget(self, #selector(transition), .touchUpInside)

        // Constrain your button here:
        mybutton.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        mybutton.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
    }

    @objc private func transition() {
        // Wait 10 secs before transitioning your images.
        DispatchQueue.main.asyncAfter(deadline: .now() + 10.0, execute: {
            mybutton.transitionImages()
        })

    }

}

推荐阅读