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

连续执行CGAffineTransform缩放动画导致视图异常变大

iOS视图缩放动画快速切换时尺寸异常变大的成因

问题场景

在iOS开发中,快速触发视图在CGAffineTransform(scaleX: 1, y: 1)与CGAffineTransform(scaleX: 0.2, y: 0.2)之间的缩放动画时,会出现视图尺寸超出预期变大的问题,演示效果如下:

问题演示录屏

示例代码:

import UIKit

class ViewController: UIViewController {
    
    let greenView = UIView()
    var isTransformed = false

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        
        view.addSubview(greenView)
        greenView.frame = CGRect(x: view.frame.midX-50, y: 150, width: 100, height: 100)
        greenView.backgroundColor = .green
        
        let transformButton = UIButton()
        transformButton.setTitle("Transform", for: .normal)
        transformButton.frame = CGRect(x: view.frame.midX-50, y: 275, width: 100, height: 40)
        transformButton.setTitleColor(.systemBlue, for: .normal)
        transformButton.addTarget(self, action: #selector(didTapTransform), for: .touchUpInside)
        view.addSubview(transformButton)
    }
    
    @objc func didTapTransform() {
        if isTransformed {
            UIView.animate(withDuration: 2) {
                var t = CGAffineTransform(scaleX: 1, y: 1)
                self.greenView.transform = t
            }
        } else {
            UIView.animate(withDuration: 2) {
                var t = CGAffineTransform(scaleX: 0.2, y: 0.2)
                self.greenView.transform = t
            }
        }
        print(greenView.transform)
        isTransformed = !isTransformed
    }
}

问题成因

核心原因是UIKit动画的实时插值特性与未完成动画的状态叠加:

  • UIKit的UIView.animate动画是基于视图的当前状态进行插值计算的。当动画正在执行时,视图的transform属性并不是设置的目标值,而是处于动画过程中的中间过渡值(比如从1缩放到0.2的过程中,可能是0.7、0.5等动态变化的值)。
  • 当快速点击按钮触发反向动画时,代码直接给视图设置新的目标transform,UIKit会把当前动画的中间过渡值作为新动画的起始值,而不是我们预期的scale=1或scale=0.2。
  • 反复快速切换动画时,每次新动画的起始点都是上一次未完成动画的中间状态,相当于多次基于动态中间值做缩放动画的叠加,最终导致视图的transform偏离预期的1或0.2,出现尺寸异常变大的情况。

举个具体例子:第一次动画从1缩放到0.2,执行到一半时transform是0.6,此时触发反向动画到1,UIKit会从0.6动画到1;如果此时再次快速切换,视图的transform可能处于0.8,又会从0.8动画到0.2,多次循环后,实际的缩放值会不断偏离初始基准值,最终出现尺寸异常。

另外,代码中直接使用CGAffineTransform(scaleX:...)是创建新的缩放变换,而非基于当前变换做修改,但由于动画未完成时的动态状态,导致新动画的起始点错误,累积后出现问题。

内容的提问来源于stack exchange,提问作者Peter Tao

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 08:57:45