Animate text Content in iOS - Equivalent for Android ValueAnimator

后端 未结 2 1542
梦谈多话
梦谈多话 2021-01-04 07:02

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 con

相关标签:
2条回答
  • 2021-01-04 07:18

    I know a solution but its for fast iteration because final iterations can jump through value (looks not beautifully if there is a slow search), but the decision simple and short, can not the most beautiful from a architecture(but it can be corrected if it is necessary) realisation.

    - (void)someAction 
    {
        [self animateValue:0 toValue:1111 withStep:7 andIntervalSpeed:5];
    }
    
    -(void)animateValue:(int)value toValue:(int)toValue withStep:(int)step andIntervalSpeed:(int64_t)intervalSpeed
    {
        self.currentValue = value; // @property (nonatomic) int currentValue;
        NSUInteger numberofIteration = (toValue - value)/step;
    
        int64_t interval = 0.0;
        for (NSUInteger i = 0; i < numberofIteration; i++) {
    
            dispatch_time_t start = DISPATCH_TIME_NOW;
            interval += intervalSpeed;
    
            dispatch_after(dispatch_time(start, interval * USEC_PER_SEC), dispatch_get_main_queue(), ^{
    
                if (((toValue - value)%step != 0) && (i == (numberofIteration-1)))
                {
                    self.currentValue = toValue;
                }
                else
                {
                    self.currentValue+= step;
                }
    
                NSLog(@"%d",self.currentValue);
                self.someLabel.text = [NSString stringWithFormat:@"%d",self.currentValue];
    
            });
    
        }
    }
    
    0 讨论(0)
  • 2021-01-04 07:19

    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 :-)

    0 讨论(0)
提交回复
热议问题