在开发的过程中,我们经常会遇到这样的需求,label显示的区域是一定的,但是内容text是不固定的,可能很长,长到这个label根本显示不下当前的内容,这种情况通常有两种处理方案:一是我们设置lineBreakMode属性,这是个枚举,我们可以根据产品的设计进行不同的方式处理,如下图(处理后对应的格式可以参照图中的注释):

        第二种处理方案就是让这个label滚动显示,这就是今天要介绍的。
label滚动大致的思路就是创建一个UIView,然后再这个UIView上创建两个label,让这个两个label反复的显示。

        下面我们具体的讲一下流程:
首先创建一个继承UIView的子类LBScrollLabel,考虑到label有可能朝着上下左右四个方向滚动,所以在这里我定义了一个枚举:

1
2
3
4
5
6
typedef NS_ENUM(NSInteger,LBScrollLabelDirection) {
LBScrollLabelDirection_Top, //from bottom to top
LBScrollLabelDirection_Bottom,
LBScrollLabelDirection_Left,
LBScrollLabelDirection_Right,
};

然后我们创建两个UILabel,分别命名成aLabelbLabel吧,初始化完成之后,我们把两个labelframe设置的和LBScrollLabel的一样大并且添加到LBScrollLabel上,具体默认的摆放,如下图:

然后我们可以给label赋值,考虑到label.text的文字可能很长,所以我们需要针对处理,具体的规则就是当text的长度小于等于LBScrollLabel的长度时候,我们把aLabelbLabel的长宽设置和LBScrollLabel相等就行了,如果text的长度大于LBScrollLabel的长度时候,我们需要按照text的长度来设置aLabelbLabel的长度,具体代码实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (void)handelLabeltextLength
{
if (self.direction == LBScrollLabelDirection_Top || self.direction == LBScrollLabelDirection_Bottom) {
_aLabel.frame = CGRectMake(_aLabel.frame.origin.x, _aLabel.frame.origin.y, width, height);
_bLabel.frame = CGRectMake(_bLabel.frame.origin.x, _bLabel.frame.origin.y, width, height);
}else if (self.direction == LBScrollLabelDirection_Left || self.direction == LBScrollLabelDirection_Right) {
[_aLabel sizeToFit];
[_bLabel sizeToFit];
if (CGRectGetWidth(_aLabel.frame) <= width) {
//
_aLabel.frame = CGRectMake(_aLabel.frame.origin.x, _aLabel.frame.origin.y, width, height);
_bLabel.frame = CGRectMake(_bLabel.frame.origin.x, _bLabel.frame.origin.y, width, height);
}else{
_aLabel.frame = CGRectMake(_aLabel.frame.origin.x, _aLabel.frame.origin.y, CGRectGetWidth(_aLabel.frame), height);
_bLabel.frame = CGRectMake(CGRectGetMaxX(_aLabel.frame), _bLabel.frame.origin.y, CGRectGetWidth(_aLabel.frame), height);
}
}
}

然后我们在LBScrollLabel.h文件中定义一个方法- (void)beginScrollWithDirection:(LBScrollLabelDirection)direction;,来控制label滚动,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- (void)beginScrollWithDirection:(LBScrollLabelDirection)direction {
self.direction = direction;
//move distance per second
distance = LBScrollSpeed * 0.01;
//handel long text
[self handelLabeltextLength];
//set _bLabel's position
if (_direction == LBScrollLabelDirection_Top) {
_bLabel.frame = CGRectMake(0, height, CGRectGetWidth(_bLabel.frame), height);
}else if (_direction == LBScrollLabelDirection_Bottom) {
_bLabel.frame = CGRectMake(0, -height, CGRectGetWidth(_bLabel.frame), height);
}else if (_direction == LBScrollLabelDirection_Left) {
_bLabel.frame = CGRectMake(CGRectGetMaxX(_aLabel.frame), 0, CGRectGetWidth(_bLabel.frame), height);
}else if (_direction == LBScrollLabelDirection_Right) {
_bLabel.frame = CGRectMake(-CGRectGetMaxX(_aLabel.frame), 0, CGRectGetWidth(_bLabel.frame), height);
}
if (timer != nil) {
[timer invalidate];
timer = nil;
}
timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(animationLabel) userInfo:nil repeats:YES];
}

label滚动我们需要考虑到滚动的速度,所以我定义了一个宏,设置了label的速度:

1
2
//default speed 10
#define LBScrollSpeed 10

最后我们定义一个NSTimer定时器,根据不同的滚动方向,移动aLabelbLabel的位置,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
- (void)animationLabel {

switch (_direction) {
case LBScrollLabelDirection_Top:
{
if (fabs(CGRectGetMinY(_aLabel.frame))>=height) {
_aLabel.frame = CGRectMake(0, 0, CGRectGetWidth(_aLabel.frame), height);
_bLabel.frame = CGRectMake(0, height, CGRectGetWidth(_bLabel.frame), height);
}
_aLabel.frame = CGRectMake(0, CGRectGetMinY(_aLabel.frame) - distance, CGRectGetWidth(_aLabel.frame), height);
_bLabel.frame = CGRectMake(0, CGRectGetMinY(_bLabel.frame) - distance, CGRectGetWidth(_bLabel.frame), height);
}
break;
case LBScrollLabelDirection_Bottom:
{
if (fabs(CGRectGetMinY(_aLabel.frame))>=height) {
_aLabel.frame = CGRectMake(0, 0, CGRectGetWidth(_aLabel.frame), height);
_bLabel.frame = CGRectMake(0, -height, CGRectGetWidth(_bLabel.frame), height);
}
_aLabel.frame = CGRectMake(0, CGRectGetMinY(_aLabel.frame) + distance, CGRectGetWidth(_aLabel.frame), height);
_bLabel.frame = CGRectMake(0, CGRectGetMinY(_bLabel.frame) + distance, CGRectGetWidth(_bLabel.frame), height);
}
break;
case LBScrollLabelDirection_Left:
{
if (fabs(CGRectGetMinX(_aLabel.frame))>=CGRectGetWidth(_aLabel.frame)) {
_aLabel.frame = CGRectMake(0, 0, CGRectGetWidth(_aLabel.frame), height);
_bLabel.frame = CGRectMake(CGRectGetMaxX(_aLabel.frame), 0, CGRectGetWidth(_bLabel.frame), height);
}
_aLabel.frame = CGRectMake(CGRectGetMinX(_aLabel.frame) - distance, 0, CGRectGetWidth(_aLabel.frame), height);
_bLabel.frame = CGRectMake(CGRectGetMinX(_bLabel.frame) - distance, 0, CGRectGetWidth(_bLabel.frame), height);
}
break;
case LBScrollLabelDirection_Right:
{
if (fabs(CGRectGetMinX(_aLabel.frame))>=CGRectGetWidth(_aLabel.frame)) {
_aLabel.frame = CGRectMake(0, 0, CGRectGetWidth(_aLabel.frame), height);
_bLabel.frame = CGRectMake(-CGRectGetMaxX(_aLabel.frame), 0, CGRectGetWidth(_bLabel.frame), height);
}
_aLabel.frame = CGRectMake(CGRectGetMinX(_aLabel.frame) + distance, 0, CGRectGetWidth(_aLabel.frame), height);
_bLabel.frame = CGRectMake(CGRectGetMinX(_bLabel.frame) + distance, 0, CGRectGetWidth(_bLabel.frame), height);
}
break;
}
}

使用的时候非常简单,代码如下:

1
2
3
4
5
LBScrollLabel *tempLB = [[LBScrollLabel alloc] initWithFrame:CGRectMake(20, 500, CGRectGetWidth(self.view.frame) - 40, 30)];
tempLB.backgroundColor = [UIColor colorWithRed:(arc4random()%255)/255.0 green:(arc4random()%255)/255.0 blue:(arc4random()%255)/255.0 alpha:1];
tempLB.text = @"This is a scroll label";
[tempLB beginScrollWithDirection:LBScrollLabelDirection_Left];
[self.view addSubview:tempLB];

        上下左右不同方向的滚动效果如下图:

本文Demo