金额跳动动画效果

引言:


# 一. 效果


# 二. 代码实现

#import <UIKit/UIKit.h>

@interface UILabel (Extension)

/// 跳动文字
@property (nonatomic, strong) NSNumber *lc_number;

@end

UILabel+Extension.m: 通过 runtime 建立属性(setter/getter方法)

#import "UILabel+Extension.h"
#import <objc/runtime.h>


#define kTimer          @"timer"
#define kAnimatedNumber @"animatedNumber"
#define kValueString    @"valueString"
#define kRangeNumberKey @"RangeKey"         // 每次数字跳动相差的间隔数
#define kBeginNumberKey @"BeginNumberKey"   // 起始数字
#define kEndNumberKey   @"EndNumberKey"     // 结束跳动时的数字
#define kFrequency      1.0/30.0f           // 数字跳动频率

#define kRangeNumber(endNumber,duration) (endNumber * kFrequency)/duration

@interface UILabel ()

@property (nonatomic, strong) NSNumber *animatedNumber;
@property (nonatomic, strong) NSTimer  *timer;
@property (nonatomic, strong) NSString *valueString;

@end

@implementation UILabel (Extension)

#pragma mark - ------ UI ------

- (void)setLc_number:(NSNumber *)lc_number {
    [self dw_setNumber:lc_number duration:1.0];
}

- (void)setAnimatedNumber:(NSNumber *)animatedNumber {
    objc_setAssociatedObject(self, kAnimatedNumber, animatedNumber, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSNumber *)animatedNumber {
    return objc_getAssociatedObject(self, kAnimatedNumber);
}

- (void)setTimer:(NSTimer *)timer {
    objc_setAssociatedObject(self, kTimer, timer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSTimer *)timer {
    return objc_getAssociatedObject(self, kTimer);
}

-(void)setValueString:(NSString *)valueString {
    objc_setAssociatedObject(self, kValueString, valueString, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSString *)valueString {
    return objc_getAssociatedObject(self, kValueString);
}

- (void)dw_setNumber:(NSNumber *)number duration:(NSTimeInterval)duration {
    
    [self.timer invalidate];
    self.timer = nil;
    
    //变量初始化
    self.animatedNumber = @(0);
    double beginNumber = 1;
    double endNumber = [number doubleValue];
    
    NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithCapacity:0];
    
    [userInfo setObject:@(beginNumber) forKey:kBeginNumberKey];
    [userInfo setObject:number forKey:kEndNumberKey];
    [userInfo setObject:@(kRangeNumber(endNumber, duration)) forKey:kRangeNumberKey];
    
    // 添加定时器,添加到NSRunLoop中
    self.timer = [NSTimer scheduledTimerWithTimeInterval:kFrequency target:self selector:@selector(changeAnimation:) userInfo:userInfo repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}

- (void)changeAnimation:(NSTimer *)timer{
    
    NSMutableDictionary *info = timer.userInfo;
    double begin = ((NSNumber *)[info objectForKey:kBeginNumberKey]).doubleValue;
    double end   = ((NSNumber *)[info objectForKey:kEndNumberKey]).doubleValue;
    double range = ((NSNumber *)[info objectForKey:kRangeNumberKey]).doubleValue;
    
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    [formatter setNumberStyle:NSNumberFormatterNoStyle];
    [formatter setFormatWidth:9];
    [formatter setPositiveFormat:@",##0.00"];
    
    double value = self.valueString.doubleValue;
    
    if (value == 0) {
        self.valueString = [NSString stringWithFormat:@"%f", begin];
        self.text = [NSString stringWithFormat:@"%.@",[formatter stringFromNumber:@(begin)]];
        
    } else if (value >= end) {
        self.text = [NSString stringWithFormat:@"%.@",[formatter stringFromNumber:@(end)]];
        self.valueString = [NSString stringWithFormat:@"%f", begin];
        [self.timer invalidate];
        self.timer = nil;
        return;
    } else {
        value += range;
        self.valueString = [NSString stringWithFormat:@"%f", value];
        self.text = [NSString stringWithFormat:@"%.@",[formatter stringFromNumber:@(value)]];
    }
}