IU大法

效果

实际项目中很常见的效果,如下:

效果.gif

思路

让label的宽度自适应内容,然后放到一个背景view上,背景view的clipsToBounds开启。持续的改变label的frame,当label末端的x坐标为0时,调整其首端x坐标。如下,不停的执行这段代码:

1
2
3
4
5
6
7
/** 刷新跑马灯label的位置 */
- (void)refreshMarqueeLabelFrame {
_marqueeLabel.maxX -= 0.3;
if (_marqueeLabel.maxX <= 0) {
_marqueeLabel.x = self.width - 41 - 38;
}
}

代码

代码没亮点,关键是思路

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
@implementation CQMarqueeView{
UILabel *_marqueeLabel;
/** 控制跑马灯的timer */
NSTimer *_timer;
}
#pragma mark - 构造方法
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// UI搭建
[self setUpUI];
}
return self;
}
#pragma mark - UI搭建
/** UI搭建 */
- (void)setUpUI {
self.backgroundColor = [UIColor colorWithHexString:@"fff4d8"];
//------- 左边的喇叭 -------//
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(13, 9, 16, 12)];
[self addSubview:imageView];
imageView.image = [UIImage imageNamed:@"volume-marquee"];
//------- 右边的关闭按钮 -------//
UIButton *closeButton = [[UIButton alloc] initWithFrame:CGRectMake(self.width - 33, 0, 30, 30)];
[self addSubview:closeButton];
[closeButton setImage:[UIImage imageNamed:@"close-marquee"] forState:UIControlStateNormal];
[closeButton setImageEdgeInsets:UIEdgeInsetsMake(9, 9, 9, 9)];
[closeButton addTarget:self action:@selector(closeButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
//------- marquee View -------//
// 背景
UIView *marqueeBgView = [[UIView alloc] initWithFrame:CGRectMake(41, 0, self.width - 41 - 38, self.height)];
[self addSubview:marqueeBgView];
marqueeBgView.clipsToBounds = YES;
// marquee label
_marqueeLabel = [[UILabel alloc] initWithFrame:marqueeBgView.bounds];
[marqueeBgView addSubview:_marqueeLabel];
_marqueeLabel.textColor = [UIColor colorWithHexString:@"ff6666"];
_marqueeLabel.font = [UIFont systemFontOfSize:13];
}
#pragma mark - 关闭按钮点击
/** 关闭按钮点击 */
- (void)closeButtonClicked:(UIButton *)sender {
if (_timer) {
[_timer invalidate];
_timer = nil;
}
if ([self.delegate respondsToSelector:@selector(marqueeView:closeButtonDidClick:)]) {
[self.delegate marqueeView:self closeButtonDidClick:sender];
}
}
#pragma mark - 赋值跑马灯文字
/** 赋值跑马灯文字 */
- (void)setMarqueeText:(NSString *)marqueeText {
_marqueeText = marqueeText;
_marqueeLabel.text = _marqueeText;
[_marqueeLabel sizeToFit];
_marqueeLabel.centerY = self.height / 2;
if (_timer) {
[_timer invalidate];
_timer = nil;
}
// 从最右边开始跑
_marqueeLabel.x = self.width - 41 - 38;
_timer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(refreshMarqueeLabelFrame) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
}
/** 刷新跑马灯label的位置 */
- (void)refreshMarqueeLabelFrame {
_marqueeLabel.x -= 0.3;
if (_marqueeLabel.maxX <= 0) {
_marqueeLabel.x = self.width - 41 - 38;
}
}

注意

timer的频率设置高点,步伐设置低点,可以让动画更连贯。不过貌似timer的interval最低只能设置为0.01s。

demo

上面演示的demo

(下载iPhone或Android应用“经理人分享”,一个只为职业精英人群提供优质知识服务的分享平台。不做单纯的资讯推送,致力于成为你的私人智库。)