iosswiftxcodeanimationcalayer

Animate CALayer Contents Change


I have a CALayer that I update the contents with a CGImage of a UIImage

self.imageLayer.contents = newImage.cgImage

I want to animate this change. First I tried this and did not work:

CATransaction.begin()
CATransaction.setAnimationDuration(0.5)
self.imageLayer.contents = newImage.cgImage
CATransaction.commit()

Then I tried this, it worked, but the animation happens after the image change:

let transition = CATransition()
transition.duration = 0.5
transition.type = CATransitionType.push
transition.subtype = CATransitionSubtype.fromBottom
self.imageLayer.add(transition, forKey: nil)
self.imageLayer.contents = newImage.cgImage

I also tried this, no animation at all:

let animation = CABasicAnimation(keyPath: "contents")
animation.fromValue = self.imageLayer.contents
animation.toValue = newImage.cgImage
animation.duration = 0.5
animation.fillMode = CAMediaTimingFillMode.forwards
animation.isRemovedOnCompletion = true
self.imageLayer.add(animation, forKey: "contents")

I prefer to have the CATransition() method working, due to the animation type.


Solution

  • Change

    let transition = CATransition()
    transition.duration = 0.5
    transition.type = CATransitionType.push
    transition.subtype = CATransitionSubtype.fromBottom
    self.imageLayer.add(transition, forKey: nil)
    self.imageLayer.contents = newImage.cgImage
    

    to

    let transition = CATransition()
    transition.duration = 0.5
    transition.type = .push
    transition.subtype = .fromBottom
    CATransaction.setDisableActions(true)
    self.imageLayer.contents = newImage.cgImage
    self.imageLayer.add(transition, forKey: nil)
    

    This will cause the old contents to exit and the new contents to enter as part of the push transition.

    However, I am worried by your claim that simply setting the contents of the layer did not animate. It may be that more is going on here than you are telling us; it may be that self.imageLayer is the wrong kind of layer (for example, it might be a view's layer — it must not be).