WYCountingLabel.gif
心路簡介
在CoreAnimation
中有fromValue
和toValue
我就在想,如果把這個東西放到Label上,讓label的文字跟隨數字的變化而變化,這樣變化的Label不就出來了嗎。
一、動畫設計
CoreAnimation
是添加到layer上的,所以需要先創建一個自定義的WYCountingLayer
,要跟隨數字而變化,所以我增加了一個 wy_number
屬性,并且使用@dynamic
修飾該屬性。
1.想要在屬性改變的時候重繪,需要重寫needsDisplayForKey:
當layer的屬性發生改變的時候就會通過這個方法詢問是否需要對當前layer進行重繪。
NSString *const WYAnimationKey = @"wy_number";
+ (BOOL)needsDisplayForKey:(NSString *)key {
if ([key isEqualToString:WYAnimationKey]) {
return YES;
}
return [super needsDisplayForKey:key];
}
2.為wy_number
增加CABasicAnimation
,這樣當wy_number
發生改變的時候就會有動畫效果了,layer的隱式動畫的實現原理就是這樣的
- (id<CAAction>)actionForKey:(NSString *)event {
if (self.presentationLayer) {
if ([event isEqualToString:WYAnimationKey]) {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:WYAnimationKey];
animation.fromValue = [self.presentationLayer valueForKey:WYAnimationKey];
return animation;
}
}
return [super actionForKey:event];
}
3.創建一個WYCountingLabel
的類并且有一個wy_number
的屬性
@interface WYCountingLabel()
@property (nonatomic, strong) WYCountingLayer *countingLayer;
@end
@implementation WYCountingLabel
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self setupLayer];
}
return self;
}
- (void)awakeFromNib {
[super awakeFromNib];
[self setupLayer];
}
- (void)setupLayer {
// 一定要給countingLayer設置frame并且添加到label的layer上
// 否則countingLayer的drawInContex:方法是不會走的
self.countingLayer = [WYCountingLayer layer];
self.countingLayer.ownerLabel = self;
self.countingLayer.frame = self.bounds;
[self.layer addSublayer:_countingLayer];
}
- (void)setWy_number:(double)wy_number {
_wy_number = wy_number;
self.countingLayer.wy_number = wy_number;
}
4.重寫WYCountingLayer
的drawInContex:
方法,在這個方法中更新label
- (void)drawInContext:(CGContextRef)ctx {
[self.ownerLabel wy_updateLabelText:self.wy_number];
}
二、項目中使用
只需要把WYCountingLabel
這個類拖到項目中即可,我給WYCountingLabel
擴展了一個formatBlock可以讓label根據數字做一些個性化展示,例如加逗號等。和一個wy_countFrom:to:duration:
可以快速給label添加數字動畫的方法
github:https://github.com/wangyansnow/WYCountingLabel
例:
- (void)viewDidLoad {
[super viewDidLoad];
self.countingLabel = [[WYCountingLabel alloc] initWithFrame:CGRectMake(20, 80, 100, 24)];
[self.view addSubview:self.countingLabel];
__weak typeof(self) weakSelf = self;
[self.countingLabel setWy_FormatBlock:^NSString *(double wy_number){
return [NSString stringWithFormat:@"%.2f", wy_number];
}];
}
- (IBAction)startCountingBtnClick:(UIButton *)sender {
static double number = 1340;
number += 1457;
self.countingLabel.wy_number = number;
}
- (IBAction)fromBtnClick:(UIButton *)sender {
[self.countingLabel wy_countFrom:0 to:1576 duration:2.0];
}