UIView多按钮动画问题:如何实现按钮逐个依次执行动画
让按钮按顺序逐个执行动画的解决方案
嘿,我懂你现在的困扰——你希望这些社交按钮能按顺序一个个弹出动画,但目前它们全都是同时开始动的。问题出在你给所有动画设置了相同的延迟时间(1.0秒),所以它们会在同一时间触发。咱们来改改代码,让它们依次动起来~
问题根源
你当前的代码里,每个按钮的动画延迟都是固定的delay: 1.0,不管循环到哪个按钮,延迟时间都一样,自然会同时启动动画。
解决思路
给每个按钮设置递增的延迟时间,比如第一个按钮延迟1秒,第二个延迟2秒,第三个延迟3秒……这样就能实现逐个动画的效果。我们可以利用循环的索引来计算这个延迟值。
修改后的代码
authClicked = true var angle: CGFloat = 45.0 google = UIButton(type: .custom) facebook = UIButton(type: .custom) vk = UIButton(type: .custom) instagram = UIButton(type: .custom) regular = UIButton(type: .custom) let buttonArray = [google: "Google", facebook: "Facebook", vk: "VK", instagram: "Instagram", regular: "Regular"] // 使用enumerated()获取每个元素的索引 for (index, (button, buttonName)) in buttonArray.enumerated() { button.frame = CGRect(x: x, y: y, width: 150, height: 150) button.addTarget(self, action: #selector(self.buttonClicked), for: .touchUpInside) button.setTitle(buttonName, for: .normal) button.alpha = 0 circleButton(button: button) angle -= 45.0 view.addSubview(button) let cosX = cos(angle) * 200 let sinY = sin(angle) * 200 // 计算递增的延迟:基础延迟1秒 + 索引 * 间隔时间(这里用1秒作为间隔,你可以根据需求调整) let delay = 1.0 + Double(index) * 1.0 UIView.animate(withDuration: 1.0, delay: delay, options: [], animations: { button.transform = CGAffineTransform(translationX: cosX, y: sinY).concatenating(CGAffineTransform(scaleX: 0.5, y: 0.5)) button.alpha = 1 }) { (done) in print(done) } }
关键改动说明
- 把
for (button, buttonName) in buttonArray改成for (index, (button, buttonName)) in buttonArray.enumerated(),这样就能拿到每个按钮在数组里的位置索引。 - 计算延迟时间
let delay = 1.0 + Double(index) * 1.0:1.0是初始延迟(所有动画都会在1秒后开始依次执行)Double(index) * 1.0是每个按钮额外增加的延迟,这里设置的是每个按钮间隔1秒启动,你可以把第二个1.0改成0.5,让动画更紧凑。
可选进阶方案(链式动画)
如果你希望上一个按钮动画完全结束后,再启动下一个,而不是固定间隔,可以用动画的completion闭包来链式调用。不过这种方式需要把按钮数组改成有序的数组(比如[(UIButton, String)]),然后递归或者逐个添加动画:
let orderedButtons = [(google, "Google"), (facebook, "Facebook"), (vk, "VK"), (instagram, "Instagram"), (regular, "Regular")] func animateButton(at index: Int) { guard index < orderedButtons.count else { return } let (button, buttonName) = orderedButtons[index] // 先完成按钮的初始化设置(和之前一样) button.frame = CGRect(x: x, y: y, width: 150, height: 150) button.addTarget(self, action: #selector(self.buttonClicked), for: .touchUpInside) button.setTitle(buttonName, for: .normal) button.alpha = 0 circleButton(button: button) angle -= 45.0 view.addSubview(button) let cosX = cos(angle) * 200 let sinY = sin(angle) * 200 UIView.animate(withDuration: 1.0, delay: index == 0 ? 1.0 : 0, options: [], animations: { button.transform = CGAffineTransform(translationX: cosX, y: sinY).concatenating(CGAffineTransform(scaleX: 0.5, y: 0.5)) button.alpha = 1 }) { [weak self] done in print(done) // 上一个动画完成后,启动下一个 self?.animateButton(at: index + 1) } } // 启动第一个按钮的动画 animateButton(at: 0)
这种方式会严格按照顺序,一个动画结束后再启动下一个,适合需要精准衔接的场景。
内容的提问来源于stack exchange,提问作者user5830749
相关产品推荐
相关产品推荐

