You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:31:03