如何在链式动画中修改UIView约束?UIButton延迟链式动画实现咨询
嘿,我来帮你把这个动画实现捋清楚!你要做的是修改UIView约束的动画,同时给UIButton做两段带延迟的链式动画,用关键帧或者链式animate都能搞定,我给你详细拆解一下:
方法一:用UIView关键帧动画统一管理时间线
这种方式适合把约束动画和按钮的两段动画放在同一个时间线里,逻辑更清晰,也方便调整各个阶段的时长。
首先定义好各个阶段的时间参数,然后在关键帧动画里分阶段实现:
// 定义动画时长和延迟 let firstAnimationDuration: TimeInterval = 0.3 let delayBetweenAnimations: TimeInterval = 2.0 let secondAnimationDuration: TimeInterval = 0.35 let totalAnimationDuration = firstAnimationDuration + delayBetweenAnimations + secondAnimationDuration // 先更新你要修改的UIView约束(比如这里修改一个view的top约束) self.someViewTopConstraint.constant = 100 // 替换成你实际要修改的约束值 // 启动关键帧动画 UIView.animateKeyframes(withDuration: totalAnimationDuration, delay: 0, options: .calculationModeLinear, animations: { // 第一帧:同时执行约束动画和按钮的第一段动画 UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: firstAnimationDuration / totalAnimationDuration) { // 约束动画必须调用layoutIfNeeded触发布局更新,才能看到动画效果 self.view.layoutIfNeeded() // 按钮第一段动画:比如缩放效果 self.targetButton.transform = CGAffineTransform(scaleX: 1.2, y: 1.2) } // 第二帧:空动画,用来实现两段按钮动画之间的延迟 UIView.addKeyframe(withRelativeStartTime: firstAnimationDuration / totalAnimationDuration, relativeDuration: delayBetweenAnimations / totalAnimationDuration) { // 这里什么都不用做,就是占住这段时间,实现延迟效果 } // 第三帧:执行按钮的第二段动画 UIView.addKeyframe(withRelativeStartTime: (firstAnimationDuration + delayBetweenAnimations) / totalAnimationDuration, relativeDuration: secondAnimationDuration / totalAnimationDuration) { // 按钮第二段动画:比如恢复缩放+调整透明度 self.targetButton.transform = .identity self.targetButton.alpha = 0.8 } }, completion: { finished in // 动画全部完成后的回调,比如恢复按钮的透明度 if finished { self.targetButton.alpha = 1.0 } })
关键细节提醒:
- 修改约束后,一定要在动画块里调用
self.view.layoutIfNeeded(),UIKit会根据新约束计算布局,然后动画化布局变化,不然约束修改会直接生效,看不到动画。 relativeStartTime和relativeDuration都是相对于总时长的比例,所以要把每个阶段的时间除以总时长来计算。- 选项里的
.calculationModeLinear可以让动画的时间线更平滑,你也可以根据需求换成其他计算模式。
方法二:用链式animate+延迟回调
如果你的需求比较简单,不想用关键帧,也可以用链式的UIView.animate配合DispatchQueue.main.asyncAfter来实现两段带延迟的动画:
// 定义时间参数 let firstAnimationDuration: TimeInterval = 0.3 let delayBetweenAnimations: TimeInterval = 2.0 let secondAnimationDuration: TimeInterval = 0.35 // 第一段动画:约束修改+按钮第一段动画 UIView.animate(withDuration: firstAnimationDuration, animations: { self.someViewTopConstraint.constant = 100 self.view.layoutIfNeeded() self.targetButton.transform = CGAffineTransform(scaleX: 1.2, y: 1.2) }) { _ in // 第一段动画完成后,延迟指定时间再执行第二段动画 DispatchQueue.main.asyncAfter(deadline: .now() + delayBetweenAnimations) { UIView.animate(withDuration: secondAnimationDuration) { self.targetButton.transform = .identity self.targetButton.alpha = 0.8 } completion: { finished in if finished { self.targetButton.alpha = 1.0 } } } }
两种方式对比:
- 关键帧动画:适合整合多个并行或串行的动画,时间线管理更灵活,比如你想在延迟期间加其他动画,直接加新的关键帧就行。
- 链式animate:代码更简洁直观,适合简单的两段带延迟的场景,不需要计算总时长的比例。
额外注意事项
- 确保你要修改的约束是可变的(用
var定义,或者是IBOutlet连接的),如果是let常量的话,没法修改。 - 如果需要在动画过程中允许用户交互,可以在动画的
options里加上.allowUserInteraction。 - 如果你是在view控制器的
viewDidLoad里执行动画,记得把动画放在view.layoutIfNeeded()之后,因为刚加载时view还没完成布局,提前修改约束可能看不到效果。
内容的提问来源于stack exchange,提问作者DanielZanchi
相关产品推荐
相关产品推荐

