Swift中重复动画重置按钮位置问题求助
解决Swift重复动画中按钮位置不重置的问题
嘿,我懂你遇到的困扰——这段动画运行起来,按钮会一直往下挪,根本不会回到初始位置重复执行,对吧?问题出在UIView动画的工作机制上:当你用.repeat选项时,每次动画循环都会基于视图的当前状态(也就是上一次动画结束后的位置)来执行,所以center.y会持续累加,导致按钮越跑越远。
下面给你两种靠谱的解决方案,按需选择:
方案一:用核心动画(CABasicAnimation)推荐
核心动画作用在视图的图层(CALayer)上,不会修改视图的实际frame/center属性,动画结束后图层会自动回滚到初始状态,完美适配你这种需要重复回到起点的场景。
代码示例:
// 先保存按钮的初始Y坐标 let initialY1 = self.tileButton1.center.y let initialY2 = self.tileButton2.center.y // 计算每次动画需要移动的距离 let moveDistance = self.tileButtonExample.frame.height / CGFloat(self.clickAccuracy) // 给tileButton1创建动画 let moveAnim1 = CABasicAnimation(keyPath: "position.y") moveAnim1.fromValue = initialY1 moveAnim1.toValue = initialY1 + moveDistance moveAnim1.duration = TimeInterval(self.waitTime) moveAnim1.repeatCount = Float(self.clickAccuracy) // 重复次数 moveAnim1.timingFunction = CAMediaTimingFunction(name: .linear) // 线性动画 self.tileButton1.layer.add(moveAnim1, forKey: "tileMoveDown") // 同理给tileButton2添加动画 let moveAnim2 = CABasicAnimation(keyPath: "position.y") moveAnim2.fromValue = initialY2 moveAnim2.toValue = initialY2 + moveDistance moveAnim2.duration = TimeInterval(self.waitTime) moveAnim2.repeatCount = Float(self.clickAccuracy) moveAnim2.timingFunction = CAMediaTimingFunction(name: .linear) self.tileButton2.layer.add(moveAnim2, forKey: "tileMoveDown")
这个方案代码简洁,不需要手动管理位置重置,系统会帮你处理所有细节。
方案二:手动递归执行UIView动画(灵活可控)
如果你更习惯用UIView的动画API,可以放弃系统的.repeat选项,改用递归手动控制动画循环,每次动画结束后重置按钮位置,再启动下一次动画。
代码示例:
// 保存初始位置和移动距离 let initialY1 = self.tileButton1.center.y let initialY2 = self.tileButton2.center.y let moveDistance = self.tileButtonExample.frame.height / CGFloat(self.clickAccuracy) var currentRepeat = 0 func startTileAnimation() { // 重复次数达标后停止 guard currentRepeat < self.clickAccuracy else { return } currentRepeat += 1 UIView.animate(withDuration: TimeInterval(self.waitTime), delay: 0, options: [.allowUserInteraction, .allowAnimatedContent, .curveLinear], animations: { // 从初始位置移动到目标位置 self.tileButton1.center.y = initialY1 + moveDistance self.tileButton2.center.y = initialY2 + moveDistance }) { _ in // 动画完成后重置位置,再启动下一次循环 self.tileButton1.center.y = initialY1 self.tileButton2.center.y = initialY2 self.startTileAnimation() } } // 启动动画 startTileAnimation()
这个方案的优势是你可以在每次动画的前后加入自定义逻辑(比如播放音效、更新状态),灵活性更高。
另外提个小建议:你代码里用的UIView.setAnimationRepeatCount是比较旧的API,现在更推荐用上面两种方式来控制动画重复次数哦。
内容的提问来源于stack exchange,提问作者George
相关产品推荐
相关产品推荐

