使用UIView animateWithDuration:来实现Alpha的即时更改,而不是动画化

5
我试图通过调整 alpha 属性来实现 UIView 渐变显示的效果。我需要先渐变显示,然后保持可见状态几秒钟,最后再渐隐消失。
但是,这个渐变显示的效果不起作用,视图直接瞬间出现,而非按照0.5秒的时间间隔缓慢地呈现出来,而渐隐消失的效果却很流畅。
因此似乎渐变显示的动画并没有生效,它只是立即将 alpha 设置为 1.0。我有点不知道该怎么办了。有什么建议吗?谢谢!
-(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];
}

编辑:

如果有帮助的话,这是我从VC代码中调用它的地方:

-(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];
}
2个回答

5
您不能像那样链接动画,因为第二个动画块实际上会取消第一个动画。

您有两个选项来链接多个动画:

  1. 使用第一个动画的完成处理程序
  2. 嵌套动画,但延迟第二个动画

  1. 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];
                     }];
    
  2. 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];
    

问题出在你设置动画的方式上。

当你在一个视图上设置可动画属性时,该视图的后备数据模型会立即更新。因此,当你在第一个块中设置 alpha = 1.0 时,视图的后备数据模型就将 alpha 设置为 1.0,然后实际的动画在另一个线程上启动,以显示两个值之间的插值。

当你紧接着第一个块定义第二个块时,视图基本上会说:“好的,我需要从 1.0(我的当前值在模型中)到 0.0 进行动画”,这就是为什么你没有看到预期效果的原因。


太棒了。非常清晰易懂。谢谢你的回复,Paul。 - Murdock

-1

感谢Paul.s的提示。我认为这种预期行为有点奇怪,即使从低级别的角度看起来似乎很合理。

为了扩展Paul的两个解决方案,我认为有第三个解决方案更好。

使用GCD在淡出代码中添加延迟,如下所示:

//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];
});

这个解决方案更好,因为执行视图控制器不仅可以控制何时,还可以控制何时触发淡出效果(例如用户操作)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接