如何在Swift中实现类似Cash App的数字动画效果?
实现类似Cash App的数字滚动动画效果
- 误区纠正:NumberFormatter是用于数字格式化的工具,和动画效果无关,你之前的尝试方向不对,需要通过数值插值+逐帧更新来实现滚动动画。
- 核心思路:每次点击数字按钮时,计算目标数值,然后在动画周期内,从当前值平滑过渡到目标值,逐帧更新Label的文本内容,模拟数字滚动的效果。
原生实现方案(Swift)
步骤1:修改变量定义
把原来的字符串类型firstNum改成数值类型,用来跟踪当前和目标数值:
import UIKit class CalculatorViewController: UIViewController { // 当前显示的数值 var currentValue: Double = 0.0 // 点击按钮后要达到的目标数值 var targetValue: Double = 0.0 // 用于逐帧更新的显示链接 var displayLink: CADisplayLink? // 动画开始时间 var startTime: CFTimeInterval = 0.0 // 动画持续时间(可根据需求调整) let animationDuration: CFTimeInterval = 0.3 @IBOutlet weak var numOnScreen: UILabel! override func viewDidLoad() { super.viewDidLoad() // 初始化显示0 numOnScreen.text = "0" } }
步骤2:处理按钮点击事件
点击数字按钮时,计算目标值并启动动画:
@IBAction func numPressed(_ sender: UIButton) { let newDigit = Double(sender.tag) // 计算目标值:当前值*10 + 新数字 targetValue = currentValue * 10 + newDigit // 如果已有动画在运行,先停止 displayLink?.invalidate() // 记录动画开始时间 startTime = CACurrentMediaTime() // 创建CADisplayLink,绑定更新方法 displayLink = CADisplayLink(target: self, selector: #selector(updateLabelValue)) displayLink?.add(to: .main, forMode: .common) }
步骤3:逐帧更新Label文本
通过CADisplayLink获取每一帧的回调,计算当前应该显示的数值并更新Label:
@objc private func updateLabelValue() { let elapsedTime = CACurrentMediaTime() - startTime // 计算动画进度,最大为1.0(动画结束) let progress = min(elapsedTime / animationDuration, 1.0) // 用缓动函数让动画更自然(easeOut效果,先快后慢) let easedProgress = 1.0 - pow(1.0 - progress, 3.0) // 计算当前过渡中的数值 let intermediateValue = currentValue + (targetValue - currentValue) * easedProgress // 格式化显示为整数(如果需要小数,可改为"%.2f") numOnScreen.text = String(format: "%.0f", intermediateValue) // 动画结束后清理资源,更新当前值 if progress >= 1.0 { displayLink?.invalidate() displayLink = nil currentValue = targetValue // 确保最终显示值准确 numOnScreen.text = String(format: "%.0f", currentValue) } }
额外说明
- 缓动函数:这里用了
easeOut的缓动效果,你可以根据需求替换成其他缓动函数(比如easeIn或linear),让动画更贴近Cash App的效果。 - 小数支持:如果需要支持小数输入,只需要添加小数点按钮的逻辑,调整数值计算方式和格式化字符串即可。
- 性能:CADisplayLink会和屏幕刷新率同步,动画流畅度有保障,不会出现卡顿。
内容的提问来源于stack exchange,提问作者joshua
相关产品推荐
相关产品推荐

