iOS中的动画文本内容 - 相当于Android ValueAnimator [英] Animate text Content in iOS - Equivalent for Android ValueAnimator

查看:109
本文介绍了iOS中的动画文本内容 - 相当于Android ValueAnimator的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发iOS 7+应用程序,并希望动画更改UILabel的内容。我想要做任何图形动画,例如淡出旧内容/淡入新内容。因此iOS提供的所有标准动画功能都像Layer动画或动画块一样无法使用(至少我认为是这样)。

I am working on an iOS 7+ app and would like to animated change the content of an UILabel. I do not want do do any graphical animation like fade out old content / fade in new content. Thus all the standard animation features iOS offers like Layer animations or animation blocks cannot be uses (at least I think so).

假设UILabel显示的某些仪表值如200 V和此文本应更改为400 V。该文本不应只是从200 V跳到400 V,而应使用一些缓和功能计算:200 V,220 V,240 V......390 V,395 V...400 V

Assume the UILabel shows some meter values like "200 V" and this text should be changed to "400 V". The text should not just jump from "200 V" to "400 V" but should be counted up using some easing function: "200 V", "220 V", "240 V"... "390 V", "395 V" ... "400 V"

在Android中可以使用ValueAnimator轻松解决:

In Android could easily be solved using a 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和自己的缓动函数手动实现这种行为。

Is there such thing in iOS as well? I found different solution for this but they are all pretty old (2010/11) and all end up implementing this behavior manually using NSTimer and own easing functions.

毫无疑问,人们可以自己实现这一点,但这会非常麻烦而且不是很优雅。那么:iOS中有什么东西可以解决这个问题,或者至少有方便的第三方实现吗?

It is out of question that one can implement this on his own, but this would be quite cumbersome and not very elegant. So: Is there something build in iOS to solve this or are there at least convenient third party implementation available?

非常感谢你!

推荐答案

由于我没有找到针对此的定制解决方案,我创建了自己的:一个简单的Animator类来处理Easing:

Since I found no tailored solution for this I created my own: A simple Animator Class which handles the Easing:

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

也许不是最漂亮的解决方案,但它有效: - )

Maybe not the prettiest solution but it works :-)

这篇关于iOS中的动画文本内容 - 相当于Android ValueAnimator的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆