Swift中CGAffineTransform动画duration失效:平移无效、恢复identity正常
我看你遇到了个挺头疼的小问题:调用hideCarousel执行1秒的平移动画时完全没效果,但showCarousel里用transform.identity恢复初始状态的动画却能正常跑,从你提供的动图也能明显看到这个现象——收起时没动画,展开时动画正常。
下面给你分析最可能的几个原因,以及对应的解决办法:
初始transform和目标transform完全一致:这是最常见的诱因。如果在调用
hideCarousel之前,carouselER的transform已经是CGAffineTransform(translationX: 0, y: 200)了,动画自然看不出任何变化,因为起始值和目标值完全相同。你可以在调用hideCarousel前加一行打印,快速确认初始状态:print(carouselER.transform)如果输出和你要设置的平移transform一致,那问题根源就找到了。
Auto Layout约束和transform冲突:如果你的
carouselER是用Auto Layout约束布局的,直接修改transform很容易和约束逻辑产生冲突。尤其是后续如果触发了布局更新(比如调用layoutIfNeeded),系统会自动把transform重置回约束控制的状态,导致动画被直接覆盖。这种情况下,更推荐用修改约束的方式实现动画,稳定性更高:- 先给
carouselER的关键约束(比如底部约束)创建一个IBOutlet:@IBOutlet weak var carouselBottomConstraint: NSLayoutConstraint! - 重写你的动画方法:
func hideCarousel() { // 调整约束值到你想要的隐藏位置 carouselBottomConstraint.constant = 200 UIView.animate(withDuration: 1) { self.view.layoutIfNeeded() } } func showCarousel() { // 恢复约束到初始值 carouselBottomConstraint.constant = 0 UIView.animate(withDuration: 1) { self.view.layoutIfNeeded() } }
- 先给
强制重置初始状态:如果你确定
carouselER的初始状态应该是.identity,可以在动画前先强制设置一次,确保动画有明确的起始值:func hideCarousel() { // 先重置到初始transform carouselER.transform = .identity UIView.animate(withDuration: 1) { self.carouselER.transform = CGAffineTransform(translationX: 0, y: 200) } }
你可以先试试第一种方案,打印初始transform值快速定位问题。如果是Auto Layout的问题,改用约束动画会更稳妥,毕竟transform和Auto Layout混用很容易出现各种布局异常~

内容的提问来源于stack exchange,提问作者Pablo Sanchez Gomez

