我正在使用iOS 7应用程序,并希望动画更改UILabel的内容.我不想做任何图形动画,如淡化旧内容/淡入新内容.因此,iOS提供的所有标准动画功能(如图层动画或动画块)无法使用(至少我认为).
假设UILabel显示“200 V”的仪表值,此文本应更改为“400 V”.文本不应该只是从“200 V”跳到“400 V”,而应该使用一些缓动功能计数:“200 V”,“220 V”,“240 V”…“390 V”,“395 V“…”400 V“
在Android中可以使用ValueAnimator轻松解决:
ValueAnimator animation = ValueAnimator.ofFloat(0f,1f); animation.setInterpolation(new EaSEOutInterpolator()); animation.setDuration(2500); animation.setStartDelay(500); animation.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpate(ValueAnimator animator) { float currentValue = animator.getAnimatedValue.floatValue(); label1.setText(String.format("%.2",fromValue1 + ((toValue1 - fromValue1) * currentValue))); label2.setText(String.format("%.2",fromValue2 + ((toValue2 - fromValue2) * currentValue))); ... } }); animation.start();
iOS还有这样的事情吗?我发现不同的解决方案,但它们都很旧(2010/11),并且最终都使用NSTimer和自己的缓动功能手动实现这个行为.
没有问题,可以自己实现这一点,但这将是相当麻烦,不是非常优雅.那么在iOS中有没有什么可以解决这个问题呢,还是至少有方便的第三方实现?
非常感谢你!
解决方法
因为我没有找到定制的解决方案,我创建了我自己的:一个简单的动画师类,处理轻松:
// MyValueAnimation.h typedef void (^MyAnimationBlock)(double animationValue); @interface MyValueAnimation : NSObject - (void)startAnimation:(MyAnimationBlock)animationBlock runtime:(NSUInteger)runtime delay:(NSUInteger)delay; @end // MyValueAnimation.m #import "MyValueAnimation.h" // Number of seconds between each animation step #define kStepSize 0.05 @interface MyValueAnimation () { NSTimer *timer; NSUInteger totalRunTime; // Total duration of the animation (delay not included) NSUInteger currentRuntime; // Time the animation is already running MyAnimationBlock animationBlock; } @end @implementation MyValueAnimation - (void)startAnimation:(MyAnimationBlock)block runtime:(NSUInteger)runtime delay:(NSUInteger)delay { if (timer != nil) [timer invalidate]; timer = nil; totalRunTime = runtime; animationBlock = block; currentRuntime = 0; if (block != nil) { if (delay > 0) { // Wait to delay the start. Convert delay from millis to seconds double delaySeconds = (double)delay / 1000.0; timer = [NSTimer scheduledTimerWithTimeInterval:delaySeconds target:self selector:@selector(delayTick:) userInfo:nil repeats:false]; } else { // Run the animation timer = [NSTimer scheduledTimerWithTimeInterval:kStepSize target:self selector:@selector(animationTick:) userInfo:nil repeats:true]; } } } - (void)delayTick:(NSTimer *)delayTimer { // End of delay -> run animation [delayTimer invalidate]; timer = [NSTimer scheduledTimerWithTimeInterval:kStepSize target:self selector:@selector(animationTick:) userInfo:nil repeats:true]; } - (void)animationTick:(NSTimer *)animationTimer { NSUInteger step = 1000 * kStepSize; // step size/length in milli seconds currentRuntime += step; double progress = MIN((double)currentRuntime / (double)totalRunTime,1.0); // Progress is a value between 0 and 1. The easing function maps this // to the animationValue which is than used inside the animationBlock // to calculate the current value of the animiation double animationValue = [self customEaSEOut:progress]; if (animationBlock != nil) animationBlock(animationValue); if (progress >= 1.0) { // Animation complete [timer invalidate]; timer = nil; } } - (double)customEaSEOut:(double)t { // Use any easing function you like to animate your values... // http://rechneronline.de/function-graphs/ // http://sol.gfxile.net/interpolation/ return (1 - pow(1-t,2)); } @end // ============================================================= // Some code using the animation - (void)animateValueFrom:(double)fromValue to:(double)toValue { if (valueAnimation == nil) valueAnimation = [[MyValueAnimation alloc] init]; MyAnimationBlock animationBlock = ^(double animationValue) { double currentValue = fromValue + ((toValue - fromValue) * animationValue); someLabel.text = [NSString stringWithFormat:"%dV",currentValue]; }; [valueAnimation startAnimation:animationBlock runtime:1500 delay:500]; }
也许不是最漂亮的解决方案,但它的作品:-)