JTNumberScrollAnimatedView
本人视频教程系类 iOS中CALayer的使用
效果:
Use JTNumberScrollAnimatedView for have a nice animation for display number. It's easy to use, easy to customize.
使用 JTNumberScrollAnimatedView来展示一个效果非常不错的显示数字变化的动画效果的控件,使用很简单,非常容易定制。
Usage
Basic usage - 基本的使用
You can use JTNumberScrollAnimatedView
like a normal view.
你可以像使用一个普通的view一样来使用JTNumberScrollAnimatedView
#import <UIKit/UIKit.h>
#import "JTNumberScrollAnimatedView.h" @interface ViewController : UIViewController @property (weak, nonatomic) IBOutlet JTNumberScrollAnimatedView *animatedView; @end
You just have to call setValue
with a NSNumber and use startAnimation
for launch the animation.
你只需要调用setValue方法然后执行startAnimation方法就能显示效果。
- (void)viewDidLoad
{
[super viewDidLoad];
[self.animatedView setValue:@249]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [self.animatedView startAnimation]; }
WARNING - 注意
For now the value
must be a positive integer.
现在,这个值必须是正的不能是负数。
Customization - 定制
You can easily change some properties of the animation. Each caracter have its own column
.
你可以很简单的修改以下的一些属性
textColor
font
duration
durationOffset
, delay between the end of the animation of each columndensity
, number of characters by column for the animationminLength
, you can force the minimum count of columnsisAscending
, the direction of the scroll
If you change one of this properties, you have to call setValue
for update the view.
如果你修改了其中的一个属性,你需要调用 setValue 来更新画面。
Requirements
- iOS 7 or higher iOS7 或者更高版本
- Automatic Reference Counting (ARC) ARC
//
// JTNumberScrollAnimatedView.h
// JTNumberScrollAnimatedView
//
// Created by Jonathan Tribouharet
//
#import <UIKit/UIKit.h>
@interface JTNumberScrollAnimatedView : UIView
@property (strong, nonatomic) NSNumber *value;
@property (strong, nonatomic) UIColor *textColor;
@property (strong, nonatomic) UIFont *font;
@property (assign, nonatomic) CFTimeInterval duration;
@property (assign, nonatomic) CFTimeInterval durationOffset;
@property (assign, nonatomic) NSUInteger density;
@property (assign, nonatomic) NSUInteger minLength;
@property (assign, nonatomic) BOOL isAscending;
- (void)startAnimation;
- (void)stopAnimation;
@end
//
// JTNumberScrollAnimatedView.m
// JTNumberScrollAnimatedView
//
// Created by Jonathan Tribouharet
//
#import "JTNumberScrollAnimatedView.h"
@interface JTNumberScrollAnimatedView(){
NSMutableArray *numbersText;
NSMutableArray *scrollLayers;
NSMutableArray *scrollLabels;
}
@end
@implementation JTNumberScrollAnimatedView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(!self){
return nil;
}
[self commonInit];
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if(!self){
return nil;
}
[self commonInit];
return self;
}
- (void)commonInit
{
self.duration = 1.5;
self.durationOffset = .2;
self.density = 5;
self.minLength = 0;
self.isAscending = NO;
self.font = [UIFont systemFontOfSize:[UIFont systemFontSize]];
self.textColor = [UIColor blackColor];
numbersText = [NSMutableArray new];
scrollLayers = [NSMutableArray new];
scrollLabels = [NSMutableArray new];
}
- (void)setValue:(NSNumber *)value
{
self->_value = value;
[self prepareAnimations];
}
- (void)startAnimation
{
[self prepareAnimations];
[self createAnimations];
}
- (void)stopAnimation
{
for(CALayer *layer in scrollLayers){
[layer removeAnimationForKey:@"JTNumberScrollAnimatedView"];
}
}
- (void)prepareAnimations
{
for(CALayer *layer in scrollLayers){
[layer removeFromSuperlayer];
}
[numbersText removeAllObjects];
[scrollLayers removeAllObjects];
[scrollLabels removeAllObjects];
[self createNumbersText];
[self createScrollLayers];
}
- (void)createNumbersText
{
NSString *textValue = [self.value stringValue];
for(NSInteger i = 0; i < (NSInteger)self.minLength - (NSInteger)[textValue length]; ++i){
[numbersText addObject:@"0"];
}
for(NSUInteger i = 0; i < [textValue length]; ++i){
[numbersText addObject:[textValue substringWithRange:NSMakeRange(i, 1)]];
}
}
- (void)createScrollLayers
{
CGFloat width = roundf(CGRectGetWidth(self.frame) / numbersText.count);
CGFloat height = CGRectGetHeight(self.frame);
for(NSUInteger i = 0; i < numbersText.count; ++i){
CAScrollLayer *layer = [CAScrollLayer layer];
layer.frame = CGRectMake(roundf(i * width), 0, width, height);
[scrollLayers addObject:layer];
[self.layer addSublayer:layer];
}
for(NSUInteger i = 0; i < numbersText.count; ++i){
CAScrollLayer *layer = scrollLayers[i];
NSString *numberText = numbersText[i];
[self createContentForLayer:layer withNumberText:numberText];
}
}
- (void)createContentForLayer:(CAScrollLayer *)scrollLayer withNumberText:(NSString *)numberText
{
NSInteger number = [numberText integerValue];
NSMutableArray *textForScroll = [NSMutableArray new];
for(NSUInteger i = 0; i < self.density + 1; ++i){
[textForScroll addObject:[NSString stringWithFormat:@"%ld", (number + i) % 10]];
}
[textForScroll addObject:numberText];
if(!self.isAscending){
textForScroll = [[[textForScroll reverseObjectEnumerator] allObjects] mutableCopy];
}
CGFloat height = 0;
for(NSString *text in textForScroll){
UILabel * textLabel = [self createLabel:text];
textLabel.frame = CGRectMake(0, height, CGRectGetWidth(scrollLayer.frame), CGRectGetHeight(scrollLayer.frame));
[scrollLayer addSublayer:textLabel.layer];
[scrollLabels addObject:textLabel];
height = CGRectGetMaxY(textLabel.frame);
}
}
- (UILabel *)createLabel:(NSString *)text
{
UILabel *view = [UILabel new];
view.textColor = self.textColor;
view.font = self.font;
view.textAlignment = NSTextAlignmentCenter;
view.text = text;
return view;
}
- (void)createAnimations
{
CFTimeInterval duration = self.duration - ([numbersText count] * self.durationOffset);
CFTimeInterval offset = 0;
for(CALayer *scrollLayer in scrollLayers){
CGFloat maxY = [[scrollLayer.sublayers lastObject] frame].origin.y;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"sublayerTransform.translation.y"];
animation.duration = duration + offset;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
if(self.isAscending){
animation.fromValue = [NSNumber numberWithFloat:-maxY];
animation.toValue = @0;
}
else{
animation.fromValue = @0;
animation.toValue = [NSNumber numberWithFloat:-maxY];
}
[scrollLayer addAnimation:animation forKey:@"JTNumberScrollAnimatedView"];
offset += self.durationOffset;
}
}
@end