如何立即移动CALayer(无动画)


Answers:


166

您要将呼叫包装在以下内容中:

[CATransaction begin]; 
[CATransaction setValue: (id) kCFBooleanTrue forKey: kCATransactionDisableActions];
layer.position = CGPointMake(x, y);
[CATransaction commit];

1
就是这样 我什至没有想到CATransaction。非常感谢!
梅尔

5
是的,六年半后。仍然有帮助。:D
Fogmeister 2014年

1
iOS7支持新的缩写:[UIView performWithoutAnimation:<#^(void)actionsWithoutAnimation#>];
k06a 2014年

2
7年7个月17天后:仍然有帮助。谢谢!
kanobius

1
竖起大拇指9年后
nshuman 2017年

32

Swift 3扩展名:

extension CALayer {
    class func performWithoutAnimation(_ actionsWithoutAnimation: () -> Void){
        CATransaction.begin()
        CATransaction.setValue(true, forKey: kCATransactionDisableActions)
        actionsWithoutAnimation()
        CATransaction.commit()
    }
}

用法:

CALayer.performWithoutAnimation(){
    someLayer.position = newPosition
}

1
@noescape属性添加到块中以允许(并明确说明)self块中不需要的属性很有用
Andrew

22

您还可以使用便捷功能

[CATransaction setDisableActions:YES] 

也一样

注意:请务必阅读Yogev Shelly的评论,以了解可能发生的任何陷阱。


5
重要的是,这会影响所有CALayer,因此您要在完成后重新启用操作,例如[CATransaction setDisableActions:YES]
Yogev Shelly 2012年

该死的我应该这么说。好保存。该命令将禁用动画,直到将其设置为NO为止,或者直到核心图形动画引擎完成了运行周期为止。不知道这是否是正确的词:/但是,谢谢您为所有人解决了这个问题。
Biclops

14

正如其他人所建议的,您可以使用CATransaction
因为CALayer的默认隐式动画持续时间为0.25秒,所以出现了问题。

因此,一种更简单的方法(在我看来)setDisableActions是使用setAnimationDuration的值0.0

[CATransaction begin];
[CATransaction setAnimationDuration:0.0];
layer.position = CGPointMake(x, y);
[CATransaction commit];

易于记忆,在重新阅读代码时易于理解,并且易于键入。谢谢!
T先生

3

在这里结合Swift 4的先前答案,可以清楚地使动画的持续时间明确

extension CALayer
{
    class func perform(withDuration duration: Double, actions: () -> Void) {
        CATransaction.begin()
        CATransaction.setAnimationDuration(duration)
        actions()
        CATransaction.commit()
    }
}

用法...

CALayer.perform(withDuration: 0.0) {
            aLayer.frame = aFrame
        }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.