UIView.animate执行时transform不生效 首个动画无过渡视图直接消失
问题原因
首个动画无过渡、源视图直接消失的核心原因是:调用replace方法时,源视图的初始状态(transform为默认identity)还没有被提交到系统当前渲染帧。系统会将动画块中设置的缩放为0的目标状态,与未渲染的初始状态合并计算,最终直接渲染出缩放结束的结果,看不到中间过渡过程。
解决方案
下面两种方案都可以解决这个问题:
- 方案1:将动画逻辑包装到主队列异步回调中执行,强制等待当前渲染周期结束,保证初始状态已经被系统渲染确认,适配所有调用场景:
private func replace( _ source: UIView, with destination: UIView, usingRotationEffect: Void ) { DispatchQueue.main.async { let collapsed = CGAffineTransform(scaleX: 0, y: 1) let expanded = CGAffineTransform.identity source.isHidden = false source.transform = expanded destination.isHidden = true destination.transform = collapsed source.superview?.layoutIfNeeded() UIView.animate( withDuration: 1, delay: 0, options: .curveLinear, animations: { source.transform = collapsed }, completion: { _ in source.isHidden = true destination.isHidden = false UIView.animate( withDuration: 1, delay: 0, options: .curveLinear, animations: { destination.transform = expanded }) }) } }
- 方案2:如果已经确认该方法是在主线程调用,也可以仅在设置完初始状态后主动调用父视图的
layoutIfNeeded()提交状态,不需要额外包异步逻辑。
如果需要实现更真实的翻转动画效果,建议把2D仿射变换换成带透视的3D变换,示例如下:
// 3D翻转变换示例 var perspectiveTransform = CATransform3DIdentity perspectiveTransform.m34 = -1.0 / 500 // 透视参数,数值越小透视效果越强 // 沿Y轴翻转90度的变换效果 let collapsed = CATransform3DRotate(perspectiveTransform, .pi / 2, 0, 1, 0)
内容的提问来源于stack exchange,提问作者Ihar Andreyeu
相关产品推荐
相关产品推荐

