I'm writing a little bit complex animation, which goes in 2 steps:
- Change opacity to 0 of
UIViews
that are not need to be visible and move aUIImageView
(which hasalpha = 1
) to anotherCGPoint
(position). - Change opacity of another
UIView
to 1 and the opacity of theUIImageView
from the previous step to 0, and then after the animation of this step is finished, removeUIImageView
from superview.
I've done it this way:
The first step is done without an explicit CATransaction. These 2 animations just have beginTime
set to CACurrentMediaTime()
. And I'm applying changes to the views right after layer.addAnimation(...)
call.
Everything works fine here.
In the second step implementation I call CATransaction.begin()
at the beginning.
Inside begin/commit
calls to CATransaction
I create and add 2 CABasicAnimations
to 2 different layers: one for changing the opacity from 0 to 1 (for UIView
), and one for changing the opacity from 1 to 0 (for UIImageView
). Both animations have beginTime
set to CACurrentMediaTime() + durationOfThePreviousStep
.
And right after CATransaction.begin()
I call CATransaction.setCompletionBlock({...})
, and in this completion block I apply changes to these two views: set their new alphas and remove UIImageView
from superview.
The problem is, at the end of this whole animation the UIView
that has alpha animated to 1 flashes, which means its alpha sets back to 0 (though I've set its alpha to 1 in the completion block) and right after this the completion block executes and its alpha goes up to 1 again.
Well, the question is, how to get rid of this flashing? Maybe this animation can be done in better way?
P.S. I'm not using UIView
animations because I'm interested in custom timing functions for these animations.
EDIT 1:
Here's the code. I've deleted UIImageView
alpha animation because it's not really necessary.
var totalDuration: CFTimeInterval = 0.0
// Alpha animations.
let alphaAnimation = CABasicAnimation()
alphaAnimation.keyPath = "opacity"
alphaAnimation.fromValue = 1
alphaAnimation.toValue = 0
alphaAnimation.beginTime = CACurrentMediaTime()
alphaAnimation.duration = 0.15
let alphaAnimationName = "viewsFadeOut"
view1.layer.addAnimation(alphaAnimation, forKey: alphaAnimationName)
view1.alpha = 0
view2.layer.addAnimation(alphaAnimation, forKey: alphaAnimationName)
view2.alpha = 0
view3.layer.addAnimation(alphaAnimation, forKey: alphaAnimationName)
view3.alpha = 0
view4.layer.addAnimation(alphaAnimation, forKey: alphaAnimationName)
view4.alpha = 0
// Image View moving animation.
// Add to total duration.
let rect = /* getting rect */
let newImagePosition = view.convertPoint(CGPoint(x: CGRectGetMidX(rect), y: CGRectGetMidY(rect)), fromView: timeView)
let imageAnimation = CABasicAnimation()
imageAnimation.keyPath = "position"
imageAnimation.fromValue = NSValue(CGPoint: imageView!.layer.position)
imageAnimation.toValue = NSValue(CGPoint: newImagePosition)
imageAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault)
imageAnimation.beginTime = CACurrentMediaTime()
imageAnimation.duration = 0.3
imageView!.layer.addAnimation(imageAnimation, forKey: "moveImage")
imageView!.center = newImagePosition
totalDuration += imageAnimation.duration
// Time View alpha.
CATransaction.begin()
CATransaction.setCompletionBlock {
self.timeView.alpha = 1
self.imageView!.removeFromSuperview()
self.imageView = nil
}
let beginTime = CACurrentMediaTime() + totalDuration
let duration = 0.3
alphaAnimation.fromValue = 0
alphaAnimation.toValue = 1
alphaAnimation.beginTime = beginTime
alphaAnimation.duration = duration
timeView.layer.addAnimation(alphaAnimation, forKey: "timeViewFadeIn")
/* imageView alpha animation is not necessary, so I removed it */
CATransaction.commit()
EDIT 2: Piece of code that cause the problem:
CATransaction.begin()
CATransaction.setCompletionBlock {
self.timeView.alpha = 1
}
let duration = 0.3
let alphaAnimation = CABasicAnimation()
alphaAnimation.keyPath = "opacity"
alphaAnimation.fromValue = 0.0
alphaAnimation.toValue = 1.0
alphaAnimation.duration = duration
timeView.layer.addAnimation(alphaAnimation, forKey: "timeViewFadeIn")
CATransaction.commit()
Maybe the problem is because the timeView
has a UITextField
and a UIScrollView
with 4 subviews. I've tried to replace timeView
with a snapshot of timeView
(UIImageView
), but that didn't help.
EDIT 3:
New code. With this code, timeView
always has alpha = 1
, and it also animates from 0 to 1.
CATransaction.begin()
CATransaction.setCompletionBlock {
self.imageView!.removeFromSuperview()
self.imageView = nil
}
let alphaAnimation = CABasicAnimation()
alphaAnimation.keyPath = "opacity"
alphaAnimation.fromValue = 0.0
alphaAnimation.toValue = 1.0
alphaAnimation.duration = 0.3
alphaAnimation.beginTime = beginTime
timeView.layer.addAnimation(alphaAnimation, forKey: "timeViewFadeIn")
timeView.alpha = 1.0
CATransaction.commit()