Reputation: 2520
I find at least 5 other "UIView animation doesn't work" questions, I hate to add yet another one. :(. I'm sure this isn't something specific to alpha
. Same issue with backgroundColor
. So it is something basic.
This works:
[self.view viewWithTag:kPlayView].alpha = 0.75;
[self.view viewWithTag:kCancelView].alpha = 0.75;
[self.view viewWithTag:kTapViewTag].backgroundColor = [UIColor whiteColor];
This doesn't (it doesn't do anything):
//kPlayView and kCancelView are subviews of kTapViewTag
[UIView animateWithDuration:2.0 animations:^{
[self.view viewWithTag:kPlayView].alpha = 0.75;
[self.view viewWithTag:kCancelView].alpha = 0.75;
[self.view viewWithTag:kTapViewTag].backgroundColor = [UIColor whiteColor];
} ];
Why? This is called in the gesture handler for the kTapViewTag
view. It is view with backgorundColor = [UIColor clearColor]
that I want to fade to white and change alpha of subviews to 0.75 in response to tap gesture.
UPDATE:
The reverse works. This works:
[UIView animateWithDuration:2.0 animations:^{
[self.view viewWithTag:kPlayView].alpha = 0;
[self.view viewWithTag:kCancelView].alpha = 0;
[self.view viewWithTag:kTapViewTag].backgroundColor = [UIColor clearColor];
}];
I am able to show the view that acts as a "pause/resume" without animation, and then animate the fade out. This works back and forth as long as I don't try to animate the fade in.
UPDATE 2
Here is the entire implementation for reference. Something in here? (I've looked too many times).
- (void)didTap:(id)selector
{
isPaused = (isPaused) ? NO: YES;
[self.view viewWithTag:kPlayView].userInteractionEnabled = isPaused;
[self.view viewWithTag:kCancelView].userInteractionEnabled = isPaused;
if (isPaused)
{
[self pauseLayer:self.view.layer];
[timer1 invalidate];
[timer2 invalidate];
[UIView animateWithDuration:2.0 animations:^{
[self.view viewWithTag:kPlayView].alpha = 0.75;
[self.view viewWithTag:kCancelView].alpha = 0.75;
[self.view viewWithTag:kTapViewTag].backgroundColor = [UIColor whiteColor];
} ];
}
else
{
isPaused = NO;
[UIView animateWithDuration:2.0 animations:^{
[self.view viewWithTag:kPlayView].alpha = 0;
[self.view viewWithTag:kCancelView].alpha = 0;
[self.view viewWithTag:kTapViewTag].backgroundColor = [UIColor clearColor];
}];
[self resumeLayer:self.view.layer];
[self animateNotification];
}
}
UPDATE 3
- (void)pauseLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
layer.speed = 0.0;
layer.timeOffset = pausedTime;
}
- (void)resumeLayer:(CALayer*)layer
{
CFTimeInterval pausedTime = [layer timeOffset];
layer.speed = 1.0;
layer.timeOffset = 0.0;
layer.beginTime = 0.0;
CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
layer.beginTime = timeSincePause;
}
Upvotes: 1
Views: 864
Reputation: 8570
UIView animations are a nice high level wrapper around Core Animation, which renders its animations using your view's layer. By setting the layer speed to 0 you effectively are stopping the uiview animations from starting.
When you start the layer time again you start it from exactly where it left off. The animations from before you paused and after are coalesced and nothing happens.
The reason the animations work in the other direction when you don't animate in is because of the way the animations are set up and fired. When you call [UIView animate...
it sets up a low level animation on the layer with a begin time and an end time and so on. The code you write completes instantly and the animation would begin on the next go of the runloop. Before you let everything return, however you also resume the layer's time and speed and so when it comes to do the animation everything proceeds as normal.
My guess is you don't mean to suspend the layer like this. There must be better ways of removing and stopping your animations. e.g. with UIView
you just animate the property again and it stops, with CALayer
you have removeAllAnimations
and removeAnimationForKey:
and also you can look into using -[CALayer presentationLayer]
to find out where a particular layer is on screen at a particular point in an animation and then adjust the actual layer values to match.
Upvotes: 1