作者:代培
地址:http://blog.csdn.net/dp948080952/article/details/51871485
转载请注明出处
写在前面
第一次写博客,有点小激动,同时也害怕写的很烂,所以希望大家能够包容,如果大家觉得看不下去我的博客,可以直接翻到最后有源码和demo的github地址。开发ios也有大半年了,所以想要尝试一下写点博客,好了废话不多说了下面开始正题了。
正文
简介
由于公司前段时间项目里要用到一个可以滚动的数字标签,所以就写了这样一个控件,现在有时间了,就写篇博客记录一下实现这个控件的过程。
上一张gif动画
这个控件的逻辑是当个位数从0~9~0时十位数向上滚动1,当十位完成一个0~9~0循环时,百位向上滚动1依次类推
实现思路
先说一下我实现这个控件的思路,其实比较简单,数字的每一列都是一个很长的UILabel,然后由上至下是数字0~9,当数字改变时,让这个label上下移动,产生滚动的动画,只需要计算循环的次数,滚动的方向,滚动的时间就可以了。
Talk is cheap,show you The code!
首先看一下头文件里的内容:
//
// DPScrollNumberLabel.h
// DPScrollNumberLabelDemo
//
// Created by Dai Pei on 16/5/23.
// Copyright © 2016年 Dai Pei. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface DPScrollNumberLabel : UIView
@property (nonatomic, strong)NSNumber *displayedNumber;
- (instancetype)initWithNumber:(NSNumber *)originNumber fontSize:(CGFloat)size;
- (instancetype)initWithNumber:(NSNumber *)originNumber fontSize:(CGFloat)size textColor:(UIColor *)color;
- (instancetype)initWithNumber:(NSNumber *)originNumber font:(UIFont *)font;
- (instancetype)initWithNumber:(NSNumber *)originNumber font:(UIFont *)font textColor:(UIColor *)color;
- (instancetype)initWithNumber:(NSNumber *)originNumber fontSize:(CGFloat)size rowNumber:(NSUInteger)rowNumber;
- (instancetype)initWithNumber:(NSNumber *)originNumber fontSize:(CGFloat)size textColor:(UIColor *)color rowNumber:(NSUInteger)rowNumber;
- (instancetype)initWithNumber:(NSNumber *)originNumber font:(UIFont *)font textColor:(UIColor *)color rowNumber:(NSUInteger)rowNumber;//rowNumber should less than or equal 8
- (void)changeToNumber:(NSNumber *)number animated:(BOOL)animated;
- (void)changeToNumber:(NSNumber *)number interval:(CGFloat)interval animated:(BOOL)animated;
@end
可以看到头文件里有7个初始化方法,分为两大类:规定列数和不规定列数。当规定列数时,则控件的列数固定,当传入的数字大于列数限制时函数直接返回,当不规定列数时,以初始化传入的数字的列数为初始列数,当后面传入的数字大于初始列数时,会自动在左边补加列(最大列数不能超过8列)
其中最重要的一个参数是字体的大小,我需要这个参数去计算此控件的大小。
另外两个方法当需要显示的数字改变时调用,animated传入YES时会有动画,传入NO时直接改变不播放动画。
下面只贴上其中一个init方法:
- (instancetype)initWithNumber:(NSNumber *)originNumber fontSize:(CGFloat)size textColor:(UIColor *)color rowNumber:(NSUInteger)rowNumber {
self = [super init];
if (self) {
self.displayedNumber = originNumber;
self.font = [UIFont systemFontOfSize:size];
self.textColor = color;
self.isAnimation = NO;
self.finishedAnimationCount = 0;
self.rowNumber = (rowNumber > 0 && rowNumber <= 8) ? rowNumber : 0;
self.maxRowNumber = (self.rowNumber == 0) ? 8 : rowNumber;
[self commonInit];
}
return self;
}
初始化后进入commonInit方法:
- (void)commonInit {
[self initCell];
[self initParent];
}
然后先初始化cell,再初始化parent:
- (void)initCell {
int originNumber = self.displayedNumber.intValue;
//如果没有规定列数 就自己计算 方法具体实现会在后面贴出
if (self.rowNumber == 0) {
self.rowNumber = [self calculateRowNumber:originNumber];
}
//用于保存所有的cell
self.cellArray = [[NSMutableArray alloc] init];
NSString *text = @"0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n0";
//这个方法很赞 可以直接根据内容来计算一个view的大小
CGRect rect = [text boundingRectWithSize:CGSizeZero
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:self.font} context:nil];
//然后保存宽度和高度值,后面很多地方都会用到
self.cellWidth = rect.size.width;
self.cellHeight = rect.size.height;
//拿到每个位数上显示的数字并保存在一个数组中
NSArray *displayNumberArray = [self getCellDisplayNumberWithNumber:self.displayedNumber.integerValue];
//初始化每个cell 并且保存在数组中
for (NSInteger i = 0; i < self.rowNumber; i++) {
UILabel *scroll