diff --git a/DPScrollNumberLabel/DPScrollNumberLabel.h b/DPScrollNumberLabel/DPScrollNumberLabel.h index e90f624..25573c8 100644 --- a/DPScrollNumberLabel/DPScrollNumberLabel.h +++ b/DPScrollNumberLabel/DPScrollNumberLabel.h @@ -30,7 +30,16 @@ typedef NS_ENUM(NSUInteger, SignSetting) { /** it synchronize with the value you set by method '-changeToNumber:animated:' and '-changeToNumber:interval:animated:' */ -@property (nonatomic, strong, readonly)NSNumber *currentNumber; +@property (nonatomic, strong, readonly) NSNumber *currentNumber; + +@property (nonatomic, strong) UIFont *font; + +@property (nonatomic, strong) UIColor *textColor; + +/// By default, when animate from 0 to 9 or from 9 to 0, there will be a big reverse animtation. Enable continuing animation by this. +@property (nonatomic, assign) BOOL continuingAnimation; + +@property (nonatomic, copy) void (^logBlock)(NSString *); /** dynamic init method, the instance created by this method have a dynamic row count, it's row will change with the value you setting @@ -39,7 +48,7 @@ typedef NS_ENUM(NSUInteger, SignSetting) { @param fontSize: the number font size you want @return the instance of DPScrollNumberLabel */ -- (instancetype)initWithNumber:(NSNumber *)number fontSize:(CGFloat)fontSize; +- (nonnull instancetype)initWithNumber:(NSNumber *)number fontSize:(CGFloat)fontSize; /** dynamic init method, the instance created by this method have a dynamic row count, it's row will change with the value you setting @@ -49,7 +58,7 @@ typedef NS_ENUM(NSUInteger, SignSetting) { @param textColor: the number color you want @return the instance of DPScrollNumberLabel */ -- (instancetype)initWithNumber:(NSNumber *)number fontSize:(CGFloat)fontSize textColor:(UIColor *)textColor; +- (nonnull instancetype)initWithNumber:(NSNumber *)number fontSize:(CGFloat)fontSize textColor:(UIColor *)textColor; /** dynamic init method, the instance created by this method have a dynamic row count, it's row will change with the value you setting @@ -59,7 +68,7 @@ typedef NS_ENUM(NSUInteger, SignSetting) { @param signSetting: the sign setting for DPScrollNumberLabel, you have three option: unsigned, normal, signed. see SignSetting enum declaration for detail. @return the instance of DPScrollNumberLabel */ -- (instancetype)initWithNumber:(NSNumber *)number fontSize:(CGFloat)fontSize signSetting:(SignSetting)signSetting; +- (nonnull instancetype)initWithNumber:(NSNumber *)number fontSize:(CGFloat)fontSize signSetting:(SignSetting)signSetting; /** dynamic init method, the instance created by this method have a dynamic row count, it's row will change with the value you setting @@ -70,7 +79,7 @@ typedef NS_ENUM(NSUInteger, SignSetting) { @param signSetting: the sign setting for DPScrollNumberLabel, you have three option: unsigned, normal, signed. see SignSetting enum declaration for detail. @return the instance of DPScrollNumberLabel */ -- (instancetype)initWithNumber:(NSNumber *)number fontSize:(CGFloat)fontSize textColor:(UIColor *)textColor signSetting:(SignSetting)signSetting; +- (nonnull instancetype)initWithNumber:(NSNumber *)number fontSize:(CGFloat)fontSize textColor:(UIColor *)textColor signSetting:(SignSetting)signSetting; /** dynamic init method, the instance created by this method have a dynamic row count, it's row will change with the value you setting @@ -79,7 +88,7 @@ typedef NS_ENUM(NSUInteger, SignSetting) { @param font: the number font you want @return the instance of DPScrollNumberLabel */ -- (instancetype)initWithNumber:(NSNumber *)number font:(UIFont *)font; +- (nonnull instancetype)initWithNumber:(NSNumber *)number font:(UIFont *)font; /** dynamic init method, the instance created by this method have a dynamic row count, it's row will change with the value you setting @@ -89,7 +98,7 @@ typedef NS_ENUM(NSUInteger, SignSetting) { @param textColor: the number color you want @return the instance of DPScrollNumberLabel */ -- (instancetype)initWithNumber:(NSNumber *)number font:(UIFont *)font textColor:(UIColor *)textColor; +- (nonnull instancetype)initWithNumber:(NSNumber *)number font:(UIFont *)font textColor:(UIColor *)textColor; /** dynamic init method, the instance created by this method have a dynamic row count, it's row will change with the value you setting @@ -99,7 +108,7 @@ typedef NS_ENUM(NSUInteger, SignSetting) { @param signSetting: the sign setting for DPScrollNumberLabel, you have three option: unsigned, normal, signed. see SignSetting enum declaration for detail. @return the instance of DPScrollNumberLabel */ -- (instancetype)initWithNumber:(NSNumber *)number font:(UIFont *)font signSetting:(SignSetting)signSetting; +- (nonnull instancetype)initWithNumber:(NSNumber *)number font:(UIFont *)font signSetting:(SignSetting)signSetting; /** dynamic init method, the instance created by this method have a dynamic row count, it's row will change with the value you setting @@ -110,7 +119,7 @@ typedef NS_ENUM(NSUInteger, SignSetting) { @param signSetting: the sign setting for DPScrollNumberLabel, you have three option: unsigned, normal, signed. see SignSetting enum declaration for detail. @return the instance of DPScrollNumberLabel */ -- (instancetype)initWithNumber:(NSNumber *)number font:(UIFont *)font textColor:(UIColor *)textColor signSetting:(SignSetting)signSetting; +- (nonnull instancetype)initWithNumber:(NSNumber *)number font:(UIFont *)font textColor:(UIColor *)textColor signSetting:(SignSetting)signSetting; /*-------------------------------------------- dynamic init method end ------------------------------------------------- @@ -132,7 +141,7 @@ typedef NS_ENUM(NSUInteger, SignSetting) { @param rowNumber: the row count of DPScrollNumberLabel, it means the row count will be changeless @return the instance of DPScrollNumberLabel */ -- (instancetype)initWithNumber:(NSNumber *)number +- (nonnull instancetype)initWithNumber:(NSNumber *)number fontSize:(CGFloat)fontSize rowNumber:(NSUInteger)rowNumber; @@ -146,7 +155,7 @@ typedef NS_ENUM(NSUInteger, SignSetting) { @param rowNumber: the row count of DPScrollNumberLabel, it means the row count will be changeless @return the instance of DPScrollNumberLabel */ -- (instancetype)initWithNumber:(NSNumber *)number +- (nonnull instancetype)initWithNumber:(NSNumber *)number fontSize:(CGFloat)fontSize textColor:(UIColor *)textColor rowNumber:(NSUInteger)rowNumber; @@ -161,7 +170,7 @@ typedef NS_ENUM(NSUInteger, SignSetting) { @param rowNumber: the row count of DPScrollNumberLabel, it means the row count will be changeless @return the instance of DPScrollNumberLabel */ -- (instancetype)initWithNumber:(NSNumber *)number +- (nonnull instancetype)initWithNumber:(NSNumber *)number fontSize:(CGFloat)fontSize signSetting:(SignSetting)signSetting rowNumber:(NSUInteger)rowNumber; @@ -177,7 +186,7 @@ typedef NS_ENUM(NSUInteger, SignSetting) { @param rowNumber: the row count of DPScrollNumberLabel, it means the row count will be changeless @return the instance of DPScrollNumberLabel */ -- (instancetype)initWithNumber:(NSNumber *)number +- (nonnull instancetype)initWithNumber:(NSNumber *)number fontSize:(CGFloat)fontSize textColor:(UIColor *)textColor signSetting:(SignSetting)signSetting @@ -193,7 +202,7 @@ typedef NS_ENUM(NSUInteger, SignSetting) { @param rowNumber: the row count of DPScrollNumberLabel, it means the row count will be changeless @return the instance of DPScrollNumberLabel */ -- (instancetype)initWithNumber:(NSNumber *)number +- (nonnull instancetype)initWithNumber:(NSNumber *)number font:(UIFont *)font textColor:(UIColor *)textColor rowNumber:(NSUInteger)rowNumber; @@ -208,7 +217,7 @@ typedef NS_ENUM(NSUInteger, SignSetting) { @param rowNumber: the row count of DPScrollNumberLabel, it means the row count will be changeless @return the instance of DPScrollNumberLabel */ -- (instancetype)initWithNumber:(NSNumber *)number +- (nonnull instancetype)initWithNumber:(NSNumber *)number font:(UIFont *)font signSetting:(SignSetting)signSetting rowNumber:(NSUInteger)rowNumber; @@ -224,7 +233,7 @@ typedef NS_ENUM(NSUInteger, SignSetting) { @param rowNumber: the row count of DPScrollNumberLabel, it means the row count will be changeless @return the instance of DPScrollNumberLabel */ -- (instancetype)initWithNumber:(NSNumber *)number +- (nonnull instancetype)initWithNumber:(NSNumber *)number font:(UIFont *)font textColor:(UIColor *)textColor signSetting:(SignSetting)signSetting diff --git a/DPScrollNumberLabel/DPScrollNumberLabel.m b/DPScrollNumberLabel/DPScrollNumberLabel.m index 4c7de89..4729f09 100644 --- a/DPScrollNumberLabel/DPScrollNumberLabel.m +++ b/DPScrollNumberLabel/DPScrollNumberLabel.m @@ -63,7 +63,6 @@ @interface DPScrollNumberLabel() @property (nonatomic, strong) NSNumber *targetNumber; @property (nonatomic, strong) NSMutableArray *cellArray; @property (nonatomic, strong) UILabel *signCell; -@property (nonatomic, assign) CGFloat fontSize; @property (nonatomic, assign) NSUInteger rowNumber; @property (nonatomic, strong) NSMutableArray *taskQueue; @property (nonatomic, assign) BOOL isAnimating; @@ -72,10 +71,9 @@ @interface DPScrollNumberLabel() @property (nonatomic, assign) CGFloat signCellHeight; @property (nonatomic, assign) NSInteger finishedAnimationCount; @property (nonatomic, assign) NSUInteger maxRowNumber; -@property (nonatomic, strong) UIColor *textColor; -@property (nonatomic, strong) UIFont *font; @property (nonatomic, assign) SignSetting signSetting; @property (nonatomic, assign) NSUInteger signRow; +@property (nonatomic, assign) BOOL fixedRowNumber; @end @@ -120,6 +118,7 @@ - (instancetype)initWithNumber:(NSNumber *)number fontSize:(CGFloat)fontSize tex self.textColor = textColor; self.isAnimating = NO; self.finishedAnimationCount = 0; + self.fixedRowNumber = rowNumber; self.rowNumber = (rowNumber > 0 && rowNumber <= 8) ? rowNumber : 0; self.maxRowNumber = (self.rowNumber == 0) ? 8 : rowNumber; self.signSetting = signSetting; @@ -161,9 +160,11 @@ - (instancetype)initWithNumber:(NSNumber *)number font:(UIFont *)font textColor: self.textColor = textColor; self.isAnimating = NO; self.finishedAnimationCount = 0; + self.fixedRowNumber = rowNumber; self.rowNumber = (rowNumber > 0 && rowNumber <= 8) ? rowNumber : 0; self.maxRowNumber = (self.rowNumber == 0) ? 8 : rowNumber; self.signSetting = signSetting; + self.logBlock = nil; [self commonInit]; } return self; @@ -193,6 +194,11 @@ - (void)initSign { } } +- (CGSize)intrinsicContentSize { + return CGSizeMake((MIN(self.rowNumber ?: [self calculateNumberRow:self.currentNumber.integerValue], self.maxRowNumber) + self.signRow) * self.cellWidth, + self.numberCellHeight/numberCellLineCount); +} + #pragma mark - ConfigViews - (void)initParent{ @@ -243,13 +249,14 @@ - (void)initCells { } - (void)updateToRowNumber:(NSInteger)rowNumber { - if (rowNumber == self.rowNumber) { + if (rowNumber == self.rowNumber || self.fixedRowNumber) { return; } [self removeAllCellFromSuperview]; [self updateCellModelToFitRowNumber:rowNumber]; [self updateCellLayoutToFitRowNumber:rowNumber withAnimation:YES]; self.rowNumber = rowNumber; + [self invalidateIntrinsicContentSize]; } - (void)removeAllCellFromSuperview { @@ -338,6 +345,7 @@ - (void)playAnimationWithChange:(NSInteger)changeValue previousNumber:(NSNumber NSArray *repeatCountArray = [self getRepeatTimesWithChangeNumber:changeValue targetNumber:self.targetNumber.integerValue]; NSArray *targetDisplayNums = [self getEachCellValueArrayWithTargetNumber:self.targetNumber.integerValue]; + NSArray *previousDisplayNums = [self getEachCellValueArrayWithTargetNumber:previousNumber.integerValue]; if (interval == 0) { interval = [self getIntervalWithPreviousNumber:previousNumber.integerValue targetNumber:self.targetNumber.integerValue]; @@ -352,11 +360,12 @@ - (void)playAnimationWithChange:(NSInteger)changeValue previousNumber:(NSNumber NSNumber *repeat = [repeatCountArray objectAtIndex:i]; NSInteger repeatCount = repeat.integerValue; NSNumber *willDisplayNum = [targetDisplayNums objectAtIndex:i]; + NSNumber *previousDisplayNum = [previousDisplayNums objectAtIndex:i]; UILabel *cell = [self.cellArray objectAtIndex:i]; CGFloat startDuration = 0; if (repeatCount == 0) { - [self makeSingleAnimationWithCell:cell duration:interval delay:delay animationCount:repeatCountArray.count displayNumber:willDisplayNum.integerValue]; + [self makeSingleAnimationWithCell:cell duration:interval delay:delay animationCount:repeatCountArray.count displayNumber:willDisplayNum.integerValue previousNumber:previousDisplayNum.integerValue]; }else { if (direction == ScrollAnimationDirectionIncrease) { @@ -407,41 +416,56 @@ - (void)makeMultiAnimationWithCell:(UILabel *)cell [UIView animateWithDuration:attribute.startDuration delay:attribute.startDelay options:UIViewAnimationOptionCurveEaseIn animations:^{ [self moveNumberCell:cell toNumber:(direction == ScrollAnimationDirectionIncrease)? 10 : 0 sign:attribute.sign]; } completion:^(BOOL finished) { - NSLog(@"start animation finish!"); + self.logBlock(@"start animation finish!"); [self moveNumberCell:cell toNumber:(direction == ScrollAnimationDirectionIncrease)? 0 : 10 sign:attribute.sign]; if (attribute.cycleDuration == 0) { [UIView animateWithDuration:attribute.endDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ [self moveNumberCell:cell toNumber:attribute.targetNumber sign:attribute.sign]; } completion:^(BOOL finished) { [self oneAnimationDidFinishedWithTotalCount:count]; - NSLog(@"end animation finish!"); + self.logBlock(@"end animation finish!"); }]; }else { [UIView animateWithDuration:attribute.cycleDuration delay:0 options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionRepeat animations:^{ [UIView setAnimationRepeatCount:attribute.repeatCount]; [self moveNumberCell:cell toNumber:(direction == ScrollAnimationDirectionIncrease) ? 10 : 0 sign:attribute.sign]; } completion:^(BOOL finished) { - NSLog(@"cycle animation finish!"); + self.logBlock(@"cycle animation finish!"); [self moveNumberCell:cell toNumber:(direction == ScrollAnimationDirectionIncrease)?0 : 10 sign:attribute.sign]; [UIView animateWithDuration:attribute.endDuration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ [self moveNumberCell:cell toNumber:attribute.targetNumber sign:attribute.sign]; } completion:^(BOOL finished) { [self oneAnimationDidFinishedWithTotalCount:count]; - NSLog(@"end animation finish!"); + self.logBlock(@"end animation finish!"); }]; }]; } }]; } -- (void)makeSingleAnimationWithCell:(UILabel *)cell duration:(CGFloat)duration delay:(CGFloat)delay animationCount:(NSInteger)count displayNumber:(NSInteger)displayNumber{ +- (void)makeSingleAnimationWithCell:(UILabel *)cell duration:(CGFloat)duration delay:(CGFloat)delay animationCount:(NSInteger)count displayNumber:(NSInteger)displayNumber previousNumber:(NSInteger)previousNumber { int sign = displayNumber >= 0 ? 1 : -1; - + void (^completionBlock)(void); + + if (self.continuingAnimation) { + if (previousNumber == 0 && displayNumber == 9) { + [self moveNumberCell:cell toNumber:10 sign:sign]; + } else if (previousNumber == 9 && displayNumber == 0) { + displayNumber = 10; + completionBlock = ^{ + [self moveNumberCell:cell toNumber:0 sign:sign]; + }; + } + } + [UIView animateWithDuration:duration delay:delay options:UIViewAnimationOptionCurveEaseOut animations:^{ [self moveNumberCell:cell toNumber:displayNumber sign:sign]; } completion:^(BOOL finished) { + if (completionBlock) { + completionBlock(); + } [self oneAnimationDidFinishedWithTotalCount:count]; - NSLog(@"single animation finish!"); + self.logBlock(@"single animation finish!"); }]; } @@ -541,7 +565,7 @@ - (NSInteger)calculateNumberRow:(NSInteger)number { return numberRow; } -- (void)moveNumberCell:(UILabel *)cell toNumber:(NSInteger)number sign:(NSInteger)sign{ +- (void)moveNumberCell:(UILabel *)cell toNumber:(NSInteger)number sign:(NSInteger)sign { CGFloat x = cell.frame.origin.x; CGFloat floatNumber = abs((int)number); CGFloat y = - self.numberCellHeight / numberCellLineCount * 10 - sign * ((CGFloat)floatNumber / numberCellLineCount) * self.numberCellHeight; @@ -614,7 +638,39 @@ - (CGFloat)getIntervalWithPreviousNumber:(NSInteger)previousNumber targetNumber: } -#pragma mark - Getters +#pragma mark - Getters & Setters + +- (void)setTextColor:(UIColor *)textColor { + _textColor = textColor; + [self.cellArray enumerateObjectsUsingBlock:^(UILabel * _Nonnull label, NSUInteger idx, BOOL * _Nonnull stop) { + label.textColor = textColor; + }]; + self.signCell.textColor = textColor; +} + +- (void)setFont:(UIFont *)font { + _font = font; + + CGRect rect = [numberCellText boundingRectWithSize:CGSizeZero + options:NSStringDrawingUsesLineFragmentOrigin + attributes:@{NSFontAttributeName:self.font} + context:nil]; + self.cellWidth = rect.size.width; + self.numberCellHeight = rect.size.height; + self.signCellHeight = rect.size.height * signCellLineCount / numberCellLineCount; + [self.cellArray enumerateObjectsUsingBlock:^(UILabel * _Nonnull label, NSUInteger idx, BOOL * _Nonnull stop) { + label.font = font; + label.frame = CGRectMake((self.rowNumber + self.signRow - 1 - idx) * self.cellWidth, 0, self.cellWidth, self.numberCellHeight); + }]; + self.signCell.font = font; + self.signCell.frame = CGRectMake(0, 0, self.cellWidth, self.signCellHeight); + self.bounds = CGRectMake(0, 0, (self.rowNumber + self.signRow) * self.cellWidth, self.numberCellHeight / numberCellLineCount); + [self invalidateIntrinsicContentSize]; +} + +- (void)setLogBlock:(void (^)(NSString *))logBlock { + _logBlock = logBlock ?: (^(NSString *l) {}); +} - (UILabel *)makeNumberCell { UILabel *cell = [[UILabel alloc] init]; @@ -635,7 +691,7 @@ - (UILabel *)signCell { _signCell.text = @"-\n \n "; break; case SignSettingUnsigned: - _signCell.text = @" \n \n "; + _signCell.text = @""; break; case SignSettingSigned: _signCell.text = @"-\n \n+";