iOS 开发 - 动画
使用 Swift 进行 iOS 开发 - 动画
Section titled “使用 Swift 进行 iOS 开发 - 动画”动画是现代用户界面的关键组成部分,通过提供视觉反馈和引导注意力来增强用户体验。在 iOS 中,动画范围广泛,从简单的视图属性变化到复杂的交互式序列。创建逐帧动画的一种基本方法是快速显示一系列图像。
创建帧动画项目——“精灵动画”
Section titled “创建帧动画项目——“精灵动画””本项目演示了一个简单的帧动画。我们将在点击按钮时,在 UIImageView 中显示一系列图像,模拟动画角色或效果。您需要一组构成动画序列的图像(GIF 的帧或精灵图)。在本示例中,假设您有命名为 frame_0.png、frame_1.png、…、frame_8.png 的图像。
要获取这些图像,您可以搜索精灵图(例如,“走路动画精灵图”)或 GIF,然后使用在线转换器或图像编辑软件将其分割成单个帧。确保图像按顺序命名。
项目设置:
- 在 Xcode 中创建一个新的 iOS 项目(App 模板,Storyboard 界面,Swift 语言)。
- 将您的动画帧图像序列(例如
frame_0.png到frame_8.png)添加到项目的资源目录(Asset Catalog,即 Assets.xcassets)中。将它们拖到资源列表中。
界面 (Main.storyboard):
- 将一个
UIImageView拖到主视图控制器的视图上。它将显示动画帧。 - 将一个
UIButton拖到视图上。将其标题设置为“切换动画”或类似文本。
UI 将包含一个图像视图(最初为空或显示第一帧)和一个用于启动/停止动画的按钮。
连接 UI 到代码 (ViewController.swift):
并排打开 Main.storyboard 和 ViewController.swift 文件。
- 从
UIImageView按住 Control 键拖动到ViewController.swift中,创建一个@IBOutlet。将其命名为animationImageView。 - 从
UIButton按住 Control 键拖动到ViewController.swift中,为“Touch Up Inside”事件创建一个@IBAction。将其命名为toggleAnimationTapped。
在 ViewController.swift 中设置动画属性:
class ViewController: UIViewController { @IBOutlet weak var animationImageView: UIImageView!
var animationFrames: [UIImage] = [] var currentFrameIndex = 0 var animationTimer: Timer? var isAnimating = false let animationDurationPerFrame: TimeInterval = 0.1 // 每秒10帧 let totalFrames = 9 // 假设图像名为 frame_0.png 到 frame_8.png
override func viewDidLoad() { super.viewDidLoad() loadAnimationFrames() // 可选地初始显示第一帧 if !animationFrames.isEmpty { animationImageView.image = animationFrames[0] } }
func loadAnimationFrames() { for i in 0..<totalFrames { if let imageName = "frame_\(i)", let image = UIImage(named: imageName) { animationFrames.append(image) } } } // ... 代码的其余部分 ...}loadAnimationFrames 函数从您的资源目录中获取 UIImage 对象并填充到数组中。名称 frame_0、frame_1 等应与您在 Asset Catalog 中使用的名称匹配。
实现动画逻辑:
@objc func updateAnimationFrame() { currentFrameIndex += 1 if currentFrameIndex >= animationFrames.count { currentFrameIndex = 0 // 循环播放动画 } if !animationFrames.isEmpty { animationImageView.image = animationFrames[currentFrameIndex] }}
@IBAction func toggleAnimationTapped(_ sender: UIButton) { if isAnimating { // 停止动画 animationTimer?.invalidate() // 停止计时器 animationTimer = nil sender.setTitle("Start Animation", for: .normal) } else { // 启动动画 if animationFrames.isEmpty { return } // 如果没有帧则不启动 currentFrameIndex = 0 // 重置到第一帧 animationImageView.image = animationFrames[currentFrameIndex]
animationTimer = Timer.scheduledTimer(timeInterval: animationDurationPerFrame, target: self, selector: #selector(updateAnimationFrame), userInfo: nil, repeats: true) sender.setTitle("Stop Animation", for: .normal) } isAnimating.toggle()}解释:
updateAnimationFrame(): 此方法由Timer调用。它前进到下一帧并更新animationImageView。当到达帧序列的末尾时,它会循环回到开头。toggleAnimationTapped(_:): 此动作方法处理按钮点击。- 如果
isAnimating为 true,它会使Timer失效(停止)并更新按钮标题为“Start Animation”。 - 如果
isAnimating为 false,它会启动一个新的Timer。Timer.scheduledTimer会按照animationDurationPerFrame指定的时间间隔重复调用updateAnimationFrame。按钮标题更新为“Stop Animation”。
- 如果
#selector(updateAnimationFrame)语法用于引用计时器的updateAnimationFrame方法。
运行应用: 构建并运行。图像视图可能会显示第一帧。点击“Start Animation”按钮。您应该看到图像视图循环显示帧,创建动画。点击“Stop Animation”暂停它。
使用 UIImageView.animationImages 的替代方法:
UIKit 也提供了一种更简单的方法来实现基本帧动画:
// 在 toggleAnimationTapped 内部,另一种实现方式:// if animationImageView.isAnimating {// animationImageView.stopAnimating()// sender.setTitle("Start Animation", for: .normal)// } else {// if animationImageView.animationImages == nil || animationImageView.animationImages?.isEmpty == true {// animationImageView.animationImages = animationFrames// animationImageView.animationDuration = TimeInterval(animationFrames.count) * animationDurationPerFrame// // animationImageView.animationRepeatCount = 0 // 0 表示无限循环// }// animationImageView.startAnimating()// sender.setTitle("Stop Animation", for: .normal)// }// isAnimating.toggle() // 您仍然需要这个状态变量或检查 animationImageView.isAnimating这个替代方法使用了 UIImageView 内置的动画属性(animationImages、animationDuration、startAnimating()、stopAnimating())。对于基本序列来说,它通常更简单。如果您需要在帧之间同步其他事件或执行动作,Timer 方法提供了更多的控制。
挑战:修改动画使其只播放一次而不是循环播放,或者添加控制动画速度的控件。