Alpha changes instantly with UIView animateWithDuration: instead of animating

I am trying to fade into the UIView that I created by animating alpha. I need to fade it, leave it visible for a few seconds, and then disappear.

The damping function works fine. The view gradually disappears. But attenuation simply makes the gaze appear instantly, rather than slowly appearing after an interval of 0.5 seconds.

So it seems that fading in the animation does not work, just setting alpha to 1.0 . I am here somehow perplexed. Any ideas what I'm doing wrong? Thanks!

 -(void)presentPopupPhrase:(NSString *)phrase inView:(UIView *)view withDelegate:(id)delegate andCompletion:(void (^)(BOOL completed))completion { MessagePopupView *pv = [[[MessagePopupView alloc] initWithFrame:self.frame andText:phrase] autorelease]; pv.alpha = 0.0; [view addSubview:pv]; [self fadeInMPV:pv withDuration:self.fadeDuration andDelay:self.fadeInDelay]; [self fadeOutMPV:pv withDuration:self.fadeDuration afterDelay:self.fadeOutDelay withCompletion:completion andDelegate:delegate]; } -(void)fadeInMPV:(MessagePopupView *)mpv withDuration:(NSTimeInterval)duration andDelay:(NSTimeInterval)delay { [UIView animateWithDuration:duration delay:delay options:UIViewAnimationOptionCurveLinear animations:^{ mpv.alpha = 1.0; } completion:nil]; } -(void)fadeOutMPV:(MessagePopupView *)mpv withDuration:(NSTimeInterval)duration afterDelay:(NSTimeInterval)delay withCompletion:(void (^)(BOOL completed))completion andDelegate:(id)delegate { [UIView animateWithDuration:duration delay:delay options:UIViewAnimationOptionCurveLinear animations:^{ mpv.alpha = 0.0; } completion:completion]; } 

EDIT:

If this helps, here is the VC code where I call it:

 -(void)viewDidAppear:(BOOL)animated { CGRect phraseFrame = CGRectMake(20, 341, 280, 65); PopupPhraseController *phraseController = [[[PopupPhraseController alloc] initWithFrame:phraseFrame] autorelease]; [phraseController presentPopupPhrase:@"Test Phrase" inView:self.view withDelegate:self andCompletion:^(BOOL completed){ if (completed) { NSLog(@"completed"); } else { NSLog(@"not completed"); } NSLog(@"blocked!"); }]; [super viewDidAppear:animated]; } 
+4
source share
2 answers

You cannot bind the animation as much as the second block of animation essentially results in the first being canceled.

You have two options for linking multiple animations together :

  • Use the handler to complete the first animation
  • An animation socket, but a delay of the second.

  • It looks something like this

     [UIView animateWithDuration:self.fadeDuration delay:self.fadeInDelay options:UIViewAnimationOptionCurveLinear animations:^{ pv.alpha = 1.0; } completion:^(BOOL finished) { [UIView animateWithDuration:self.fadeDuration delay:self.fadeOutDelay options:UIViewAnimationOptionCurveLinear animations:^{ pv.alpha = 0.0; } completion:completion]; }]; 
  • It looks something like this

     [UIView animateWithDuration:self.fadeDuration delay:self.fadeInDelay options:UIViewAnimationOptionCurveLinear animations:^{ pv.alpha = 1.0; [UIView animateWithDuration:self.fadeDuration delay:self.fadeOutDelay + self.fadeDuration options:UIViewAnimationOptionCurveLinear animations:^{ pv.alpha = 0.0; } completion:completion]; } completion:nil]; 

The problem is how you tweak the animation.

When you set the animation properties in a view, the base view model is updated instantly. Therefore, when you set alpha = 1.0 in the first block, the backup data model for the view has alpha as 1.0 , and then the actual animation runs in another thread to show the interpolation between the two values.

When you define the second block immediately after the first view, it essentially says β€œok I need to animate from 1.0 (my current value in the model) to 0.0 ”, so you don’t see what you expected.

+4
source

Thanks to Paul.s for rejecting the hint. I think this expected behavior is a little strange, even if it seems logical from a low level perspective.

To expand Paul 2's solutions, there is a 3rd solution that is better than IMO.

Use a GCD to add delay to the attenuation code, for example:

 //Make sure this delay exceeds your fade-in time... double delayInSeconds = 2.0; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ [self fadeOutMPV:pv withDuration:self.fadeDuration afterDelay:self.fadeOutDelay withCompletion:completion andDelegate:delegate]; }); 

This solution is better, because the executive controller of the view has full control not only then, but also what activates the shutdown (for example, a user action).

-1
source

Source: https://habr.com/ru/post/1446577/


All Articles