UIView动画位置跳跃



我有一个过渡动画,我需要让它看起来像VC1上的一个项目在VC2滑动到位时移动到一个新位置。我在其他过渡中没有遇到任何问题,但对于这一次,我有一个问题无法解决。

VC1-在中心有一个特定大小的图像VC2-相同的图像被放置在右上角一个较小尺寸的

所以我需要移动和扩展,因为我是在过渡期做这件事的,我认为正确的方法是:

  1. 从VC2获取图像平移并缩放以匹配VC1上的图像(使用变换)
  2. 在VC1上隐藏图像
  3. 将图像从VC2动画化回.identity

当我把东西移到左上角时,我也成功地做了同样的事情。然而,当我做这个特定的动画时,我看到我的VC2图像随着动画开始到一个新的位置而跳跃。我只有在使用比iPhone 7大或小的设备/模拟器时才会看到这种跳跃,而且它会根据屏幕宽度而不同地跳跃(左表示较小,右表示较大)。

我已经注销了我的图像在所有阶段的位置:

transform from: (x:336.0, y:35.5, w:38.0) to: (x:160.0, y:180.5, w:66.0)
xOffset: -176.0 yOffset: 145.0
transform: CGAffineTransform(a: 1.0, b: 0.0, c: 0.0, d: 1.0, tx: -176.0, ty: 145.0)
preanimation: (x: 160.0, y: 180.5
currentPosition: (midX: 105.0, midY: 180.5)
currentPosition: (midX: 112.312, midY: 174.476)

日志的第一行显示我正在将图像从(336,35)移动到(160,180.5)。第二行显示我的数学是正确的。第三行显示了创建的变换(缩放当前处于禁用状态)。第四行显示我的图像在动画开始前的正确位置。最后两行在cadisplaylink回调中返回,显示我的位置在动画开始前跳跃。

有人遇到过这样的事情吗?有什么线索可以帮我解决吗?我的图像都是用LayoutConstraints放置的,我的动画都是用变换运行的(在动画之前变换,然后动画返回.identity)

编辑:添加了一些信息,当从横向开始时,我注意到我的原始帧完全错误:

transform from: (x:336.0, y:35.5, w:38.0) to: (x:368.0, y:147.666666666667, w:66.0)
xOffset: 32.0 yOffset: 112.166666666667
transform: CGAffineTransform(a: 2.66666666666667, b: 0.0, c: 0.0, d: 2.66666666666667, tx: 32.0, ty: 112.166666666667)
preanimation: (x: 368.0, y: 147.666666666667
currentPosition: (midX: 729.0, midY: 127.666666666667)

因此,在这一点上,我认为问题是,由于自动布局约束,我试图同步到的帧在动画之前不正确。当动画开始时,所有帧都由动画使用布局约束重新计算,然后应用我的变换,使跳跃出现。

第2版:

我想我已经想通了。问题是,我正在制作动画的视图还没有布局它的子视图,所以帧是关闭的。通过在动画设置过程中对视图调用.setNeedsLayout().layoutIfNeeded(),我可以获得在它们之间制作动画的正确位置。

对于好奇的人来说,这里是我第一次编辑时的相同日志,添加了调用viewlifecycle方法的时间:

viewDidLoad <Chalkboard.SwipeToMoveViewController: 0x7fb1f760fb70>
viewWillAppear <Chalkboard.SwipeToMoveViewController: 0x7fb1f760fb70>
transform from: (x:336.0, y:35.5, w:38.0) to: (x:368.0, y:147.666666666667, w:66.0)
xOffset: 32.0 yOffset: 112.166666666667
transform: CGAffineTransform(a: 2.66666666666667, b: 0.0, c: 0.0, d: 2.66666666666667, tx: 32.0, ty: 112.166666666667)
preanimation: (x: 368.0, y: 147.666666666667
animation Block: (to.x: 368.0, to.y: 147.666666666667 - (from.x: 368.0, from.y: 147.666666666667
viewWillLayoutSubviews <Chalkboard.SwipeToMoveViewController: 0x7fb1f760fb70>
viewDidLayoutSubviews <Chalkboard.SwipeToMoveViewController: 0x7fb1f760fb70>
currentPosition: (midX: 729.0, midY: 127.666666666667)

为了防止人们不想通读文本墙来找到解决方案,问题是在布局所有视图之前,我使用了不同视图控制器中视图的位置。我认为在动画逻辑开始之前,整个视图生命周期已经在我的演示视图控制器中处理过了,我错了。

动画调用顺序:

  1. viewDidLoad
  2. 视图将出现
  3. 动画化过渡
  4. 视图WillLayout子视图
  5. viewDidLayout子视图

所以修复方法是手动调用setNeedsLayout()layoutIfNeeded()作为动画过渡的开始,这样我的视图的位置都是已知的,可以用于转换。

最新更新