零速度的CALayer不会改变它的位置

Posted

技术标签:

【中文标题】零速度的CALayer不会改变它的位置【英文标题】:CALayer with zero speed doesn't change it's position 【发布时间】:2015-02-05 16:13:31 【问题描述】:

我正在实现一个自定义的 pull-to-refresh 组件。

使用微调器动画创建 CALayer,然后将此层添加到 UICollectionView。图层的速度为零 (self.loaderLayer.speed = 0.0f;),图层动画由 scrollViewDidScroll: 中的 timeOffset 管理。问题出在这里,因为我还想始终在拉空间的中心显示一个加载器,所以我在scrollViewDidScroll: 中更改图层的位置,如下所示:

[self.loaderLayer setPosition:CGPointMake(CGRectGetMidX(scrollView.bounds), scrollView.contentOffset.y / 2)];

但是层位置没有任何反应(调用[self.loaderLayer setNeedsDisplay] 没有帮助)。我知道这是因为零速度。目前我找到了可行的方法(但我不喜欢那个):

self.loaderLayer.speed = 1.0f;
[self.loaderLayer setPosition:CGPointMake(CGRectGetMidX(scrollView.bounds), scrollView.contentOffset.y / 2)];
self.loaderLayer.speed = 0.0f;

如何更改暂停图层的位置?我错过了什么?

【问题讨论】:

speed 设置为0.0f 会导致该图层的所有动画暂停;包括定位。实现“微调器动画暂停”的方法可能与您正在执行的方法不同,但如果不查看如何构建微调器层的代码,就很难说出那是什么。 只需使用两个不同的层,一个用于设置零速度,另一个用于重新定位。一个可以包含另一个。 是的,将用第二层包裹。我只是认为,无论暂停状态如何,都有一种正确的方法可以强制更新位置。谢谢 How do you move a CALayer instantly (w/o animation) 的可能重复图层不会移动,因为默认情况下setPosition 是动画的,并且您将动画速度设置为零。所以在没有动画的情况下移动它。 @David 感谢您的参考,这正是我想要的:) 【参考方案1】:

所有关于 @David 的参考。我只是把它总结为一个答案。

CoreAnimation 适用于两种动画(事务):显式隐式。当您在 property 文档中看到 Animatable 字样时,这意味着每次您设置此属性时,CoreAnimation 将动画此属性更改隐式系统默认持续时间(默认为1/4 秒)。 CALayer 对这些属性有动作,调用 -actionForKey 会返回这样的动作(隐式动画)。

所以在我的情况下,当我更改图层位置时,CoreAnimation 会隐式尝试为这些更改设置动画。因为图层已暂停(速度为零)并且动画有默认持续时间,我们看不到这种变化。

答案是禁用隐式动画(禁用调用层-actionForKey)。为此,我们调用[CATransaction setDisableActions:YES]

我们可以通过调用[CATransaction setAnimationDuration:0.0]; 将此动画标记为立即(通过将其持续时间设置为零)。

这些标志/更改是基于每个线程的,并且适用于特定线程中的所有事务,直到下一个运行循环。因此,如果我们想将它们应用到具体的交易中,我们用[CATransaction begin]; ... [CATransaction commit]; 部分包装代码。

在我的情况下,最终代码看起来

[CATransaction begin];
[CATransaction setDisableActions:YES];
[self.loaderLayer setPosition:CGPointMake(CGRectGetMidX(scrollView.bounds), scrollView.contentOffset.y / 2)];
self.loaderLayer.transform = CATransform3DMakeScale(scaleFactor, scaleFactor, 1);
[CATransaction commit];

而且效果很好!

【讨论】:

以上是关于零速度的CALayer不会改变它的位置的主要内容,如果未能解决你的问题,请参考以下文章

滚动视图滚动时,有任何更好的方法可以无延迟地更改CAlayer位置

移动CALayer位置完全被超级CALayer封装

将 CALayer 更改应用到 UIView

iOS CALayer.zPosition 不会超越视图层次结构吗?

关于CALayer的contentsGravity属性

更新 CALayer 的旋转