基于XCode9与Swift4的UIButton动画实现技术咨询
Hey there! Let's break down how to implement the button animations you're looking for—either a full sequence of images triggered by a single tap, or a step-by-step state change on each click. I'll share code snippets tailored for Xcode 9 and Swift 4 that you can drop right into your project.
Option 1: Single Tap to Play Full Image Sequence
This approach will cycle through all your placeholder button images in order, with smooth transitions, when the button is clicked once.
Step 1: Set Up Your Assets & Button
First, add all your button state images to your Xcode Asset Catalog, then connect your button to an IBOutlet in your view controller.
Step 2: Implement the Animation Code
import UIKit class ViewController: UIViewController { @IBOutlet weak var animatedButton: UIButton! // Replace these with your actual image names from Assets private let buttonAnimationImages = [ UIImage(named: "btn_placeholder1"), UIImage(named: "btn_placeholder2"), UIImage(named: "btn_placeholder3"), UIImage(named: "btn_placeholder4") ].compactMap { $0 } // Filter out any nil images private var currentFrameIndex = 0 override func viewDidLoad() { super.viewDidLoad() // Set initial button image animatedButton.setImage(buttonAnimationImages.first, for: .normal) } @IBAction func onButtonTap(_ sender: UIButton) { playFullAnimationSequence() } private func playFullAnimationSequence() { currentFrameIndex = 0 // Recursive function to animate each image in sequence func animateNextFrame() { guard currentFrameIndex < buttonAnimationImages.count else { // Reset to first image after sequence ends animatedButton.setImage(buttonAnimationImages.first, for: .normal) currentFrameIndex = 0 return } // Use cross-dissolve transition for smooth image change UIView.transition(with: animatedButton, duration: 0.3, options: .transitionCrossDissolve, animations: { self.animatedButton.setImage(self.buttonAnimationImages[self.currentFrameIndex], for: .normal) }, completion: { _ in self.currentFrameIndex += 1 // Delay before next frame (adjust timing as needed) DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { animateNextFrame() } }) } animateNextFrame() } }
Option 2: Step-by-Step State Change on Each Tap
If you want the button to switch to the next state/image every time it's clicked (instead of playing the full sequence at once), use this simplified tap handler:
@IBAction func onButtonTap(_ sender: UIButton) { // Cycle to next image, loop back to start if at the end currentFrameIndex = (currentFrameIndex + 1) % buttonAnimationImages.count // Animate the image switch UIView.transition(with: sender, duration: 0.3, options: .transitionCrossDissolve, animations: { sender.setImage(self.buttonAnimationImages[self.currentFrameIndex], for: .normal) }, completion: nil) }
Bonus: Add Custom Animations (e.g., Scale/Color)
If your reference images include effects like button scaling or color shifts, you can combine those with the image transitions:
UIView.animate(withDuration: 0.3, animations: { // Scale the button up slightly sender.transform = CGAffineTransform(scaleX: 1.1, y: 1.1) // Change background color (adjust to your desired colors) sender.backgroundColor = UIColor.systemBlue }) { _ in // Animate back to original state UIView.animate(withDuration: 0.3) { sender.transform = .identity sender.backgroundColor = UIColor.systemGray } }
Key Notes for Xcode 9 + Swift 4
compactMapis used here (instead offlatMap) which is the correct Swift 4 syntax for filtering nil values.- All animations run on the main thread, which is required for UI updates in iOS.
- Ensure your images are the same size to prevent button layout glitches.
Hope these implementations fit your needs! Feel free to adjust animation durations, transition styles, or add more custom effects to match your design exactly.
内容的提问来源于stack exchange,提问作者MoonMan

