如何为UILabel添加脉动动画效果?

14

我正在尝试使UILabel中的文本颜色动画脉冲,从[黑色]到[白色]再到[黑色]并重复。

- (void)timerFlash:(NSTimer *)timer {
[[self navTitle] setTextColor:[[UIColor whiteColor] colorWithAlphaComponent:0.0]];
[UIView animateWithDuration:1
                      delay:0 
                    options:UIViewAnimationOptionAllowUserInteraction 
                 animations:^{[[self navTitle] setTextColor:[[UIColor whiteColor] colorWithAlphaComponent:1.0]];} 
                 completion:nil];
}

.

[self setFadeTimer:[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerFlash:) userInfo:nil repeats:YES]];
首先,我对我的方法不确定,我的计划(如上所述)是设置一个动画块,并使用重复的NSTimer调用它,直到取消。
其次,我的第二个问题(如上所述)是,我正在从黑色(alpha 0)动画到白色(alpha 1),但我不知道如何再次动画回黑色,使动画无缝循环。
本质上,我想要的是在UILabel上脉冲文本颜色,直到用户按下按钮继续。
编辑_001:
我遇到麻烦,因为您无法动画化[UILabel setColor:],但是您可以动画化[UILabel setAlpha:],所以我将尝试一下。
编辑_002:
- (void)timerFlash:(NSTimer *)timer {
    [[self navTitle] setAlpha:0.5];
    [UIView animateWithDuration:2 
                          delay:0 
                        options:UIViewAnimationOptionAllowUserInteraction 
                     animations:^{[[self navTitle] setAlpha:0.9];} 
                     completion:nil];
}

这个可以运行(顺便说一下:我想要它停止,这也是我将其连接到NSTimer的原因,这样我就可以取消它),唯一的问题是它从中灰色变成近白色,然后弹回来。有人知道如何从近白色重新动画到中灰色,以便我得到一个漂亮的平滑循环吗? 输入图像描述

编辑_003:(解决方案)

戴夫·德隆(Dave DeLong)建议的代码(见下文),在修改为使用CALayer不透明度样式属性时确实有效:

UILabel *navTitle;
@property(nonatomic, retain) UILabel *navTitle;

.

// ADD ANIMATION
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"opacity"];
[anim setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[anim setFromValue:[NSNumber numberWithFloat:0.5]];
[anim setToValue:[NSNumber numberWithFloat:1.0]];
[anim setAutoreverses:YES];
[anim setDuration:0.5];
[[[self navTitle] layer] addAnimation:anim forKey:@"flash"];

.

// REMOVE ANIMATION
[[[self navTitle] layer] removeAnimationForKey:@"flash"];

我并不完全相信animateWithDuration能够与NSTimer一起使用,因为我无法让它做出除了从一个颜色突然变化到另一个颜色之外的任何动画效果。 - fuzzygoat
3个回答

15

你可以使用 CAAnimation 来实现这个功能。我之前写了一个小演示程序,将奥林匹克标志显示出来,并使五环飞到屏幕上的随机位置,然后再返回原始位置。你也可以通过类似的方式实现,但不能使用 position 属性。

以下是让其中一个圆环飞动的基本代码:

CABasicAnimation * a = [CABasicAnimation animationWithKeyPath:@"position"];
[a setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[a setFromValue:[NSValue valueWithCGPoint:[layer position]]];
[a setToValue:[NSValue valueWithCGPoint:[self randomPoint]]];
[a setAutoreverses:YES];
[a setDuration:1.0];
[layer addAnimation:a forKey:nil];

你的fromValuetoValue值将会是CGColorRefs,你的动画keypath会有所不同,但这里的技巧是设置setAutoreverses:YES。这将从fromValuetoValue进行动画处理,然后返回到fromValue。这非常方便。 :)

https://github.com/davedelong/Demos/blob/master/OlympicRings


如果这种方法不起作用(可能不起作用),那么我可能只需要在彼此之上叠加两个UILabels并同时将它们的alpha值从0.0到1.0(或反之亦然)进行动画处理。


谢谢你,Dave。我会看一下的。我也认为UILabel的textColor属性不可动画化,这可能就是为什么我只能得到一个非常不够动态的弹出效果。 - fuzzygoat
嗨,我对CoreAnimation不是很熟悉,从我所看到的来看,最好的keyPath值应该是“opacity”,尽管我在UILabel或UIView上找不到直接的opacity,我可能需要尝试“alpha”,但我不确定那会怎么样。[a setFromValue:[[self navTitle] setAlpha:0.9]]; 我现在不在我的工作电脑旁边,稍后再试... - fuzzygoat

9

如果您希望这个过程无限期地发生,您可以使用Dave DeLong的回答或者这个:

[UIView animateWithDuration:1
                      delay:0 
                    options:UIViewAnimationOptionAllowUserInteraction |
                            UIViewAnimationOptionAutoreverse |
                            UIViewAnimationOptionRepeat
                 animations:^{[[self navTitle] setTextColor:[UIColor whiteColor]];} 
                 completion:nil];

使用CAAnimation的优势当然是可以随后删除动画;而使用其它方式停止动画则需要深入到CALayer中查找并停止动画。
不过,你提到UILabel.textColor可能无法进行动画化。这个可能性是存在的。如果是这样的话,你可以使用相同的技巧在两个不同颜色的UILabel之间进行转换,并且只需淡化它们的透明度值即可。

谢谢BJ,我确实希望它停止,所以我将其钩入了一个NSTimer中,这样我可以在完成后杀掉计时器。不过这些选项很有趣,我一定会记下来以备将来参考。 - fuzzygoat

1

(与此处相同{{link1:在UIView animateWithDuration中取消块}})

我只是重复动画,并使用调度块在一段时间后将其停止:

- (void)animate // Blink a view three times
{
    // We need to stop the animation after a while (0.9 sec)
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.9 * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void)
    {
        [view.layer removeAllAnimations];
        view.alpha = 0.0; // Animation clean-up
    });

    [UIView animateWithDuration:0.15 // 0.15*6=0.9: It will animate six times (three in reverse)
                          delay:0.0
                        options:UIViewAnimationOptionAutoreverse | UIViewAnimationOptionRepeat
                     animations:^{
                         view.alpha = 1.0; // Animation
                     }
                     completion:NULL];
}

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