最近闲来无事,做了一个跑马灯的效果,感觉效果还凑合,故和大家分享一下。
至于为什么说一句话,看一下我在ViewController中 初始化跑马灯的Demo:
1 WQLPaoMaView *paoma = [[WQLPaoMaView alloc]initWithFrame:CGRectMake(0, 100, self.view.frame.size.width, 50) withTitle:@"全场卖两块,买啥都两块,两块钱,你买不了吃亏,两块钱,你买不了上当,真正的物有所值。拿啥啥便宜 买啥啥不贵,都两块,买啥都两块,全场卖两块,随便挑,随便选,都两块~~ "];
2
3 [self.view addSubview:paoma];
你只需要在初始化视图时传入视图的frame、要显示的文本即可实现跑马灯的效果了。
然后看一下效果图:
可以点击停止按钮,让文本暂停滚动。点击开始按钮,让文本继续滚动。
在ViewController中需要做的事情很少,那么我们把重点放在自定义的视图中。
自定义的视图
WQLPaoMaView.h文件中:
1 #import <UIKit/UIKit.h> 2 3 @interface WQLPaoMaView : UIView 4 5 - (instancetype)initWithFrame:(CGRect)frame withTitle:(NSString *)title; 6 7 - (void)start; 8 9 - (void)stop; 10 11 @end
WQLPaoMaView.m文件:
1 - (instancetype)initWithFrame:(CGRect)frame withTitle:(NSString *)title 2 { 3 self = [super initWithFrame:frame]; 4 5 if (self) { 6 7 CGFloat viewHeight = frame.size.height; 8 labelHeight = viewHeight; 9 10 //循环的时间这里取的是4 此数越大速度越快 11 time = title.length/4; 12 13 UILabel *myLable = [[UILabel alloc]init]; 14 myLable.text = title; 15 myLable.font = [UIFont systemFontOfSize:16.0f]; 16 myLable.backgroundColor = [UIColor orangeColor]; 17 18 //计算文本的宽度 19 CGFloat calcuWidth = [self widthForTextString:title height:labelHeight fontSize:16.0f]; 20 21 //这两个frame很重要 分别记录的是左右两个label的frame 而且后面也会需要到这两个frame 22 currentFrame = CGRectMake(0, 0, calcuWidth, labelHeight); 23 behindFrame = CGRectMake(currentFrame.origin.x+currentFrame.size.width, 0, calcuWidth, labelHeight); 24 25 myLable.frame = currentFrame; 26 [self addSubview:myLable]; 27 28 labelArray = [NSMutableArray arrayWithObject:myLable]; 29 30 //如果文本的宽度大于视图的宽度才开始跑 31 if (calcuWidth>frame.size.width) { 32 UILabel *behindLabel = [[UILabel alloc]init]; 33 behindLabel.frame = behindFrame; 34 behindLabel.text = title; 35 behindLabel.font = [UIFont systemFontOfSize:16.0f]; 36 behindLabel.backgroundColor = [UIColor orangeColor]; 37 [labelArray addObject:behindLabel]; 38 [self addSubview:behindLabel]; 39 [self doAnimation]; 40 } 41 } 42 return self; 43 } 44 45 - (void)doAnimation 46 { 47 //UIViewAnimationOptionCurveLinear是为了让lable做匀速动画 48 [UIView animateWithDuration:time delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ 49 50 //取到两个label 51 UILabel *lableOne = labelArray[0]; 52 UILabel *lableTwo = labelArray[1]; 53 54 //让两个label向左平移 55 lableOne.transform = CGAffineTransformMakeTranslation(-currentFrame.size.width, 0); 56 lableTwo.transform = CGAffineTransformMakeTranslation(-currentFrame.size.width, 0); 57 58 } completion:^(BOOL finished) { 59 //两个label水平相邻摆放 内容一样 label1为初始时展示的 label2位于界面的右侧,未显示出来 60 //当完成动画时,即第一个label在界面中消失,第二个label位于第一个label的起始位置时,把第一个label放置到第二个label的初始位置 61 UILabel *lableOne = labelArray[0]; 62 lableOne.transform = CGAffineTransformIdentity; 63 lableOne.frame = behindFrame; 64 65 UILabel *lableTwo = labelArray[1]; 66 lableTwo.transform = CGAffineTransformIdentity; 67 lableTwo.frame = currentFrame; 68 69 //在数组中将第一个label放置到右侧,第二个label放置到左侧(因为此时展示的就是labelTwo) 70 [labelArray replaceObjectAtIndex:1 withObject:lableOne]; 71 [labelArray replaceObjectAtIndex:0 withObject:lableTwo]; 72 73 //递归调用 74 [self doAnimation]; 75 }]; 76 }
其实跑马灯的核心思想比较好理解,就是创建两个label循环展示。
此外,比较关键的另外两个方法就是跑马灯的开始与结束:
1 - (void)start 2 { 3 UILabel *lableOne = labelArray[0]; 4 [self resumeLayer:lableOne.layer]; 5 6 UILabel *lableTwo = labelArray[1]; 7 [self resumeLayer:lableTwo.layer]; 8 9 isStop = NO; 10 11 } 12 13 - (void)stop 14 { 15 UILabel *lableOne = labelArray[0]; 16 [self pauseLayer:lableOne.layer]; 17 18 UILabel *lableTwo = labelArray[1]; 19 [self pauseLayer:lableTwo.layer]; 20 21 isStop = YES; 22 } 23 24 //暂停动画 25 - (void)pauseLayer:(CALayer*)layer 26 { 27 CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil]; 28 29 layer.speed = 0; 30 31 layer.timeOffset = pausedTime; 32 } 33 34 //恢复动画 35 - (void)resumeLayer:(CALayer*)layer 36 { 37 //当你是停止状态时,则恢复 38 if (isStop) { 39 40 CFTimeInterval pauseTime = [layer timeOffset]; 41 42 layer.speed = 1.0; 43 44 layer.timeOffset = 0.0; 45 46 layer.beginTime = 0.0; 47 48 CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil]-pauseTime; 49 50 layer.beginTime = timeSincePause; 51 } 52 53 }
这样就搭建好了整个自定义跑马灯视图。
动画的暂停与开始的实质就是:使用动画,让label滚动,在点击开始时,让动画开始。点击结束时,让动画暂停。
感兴趣的小伙伴可以查看完整Demo(附有注释):https://github.com/Coolll/WQLPaoMaView
欢迎大家提出各种建议和意见,探讨才能成长。
针对那位评论说:”CPU的占用率100%“ 的那位同学,特意截一个真机运行的图给你,请好好检查一下代码,全部就只有两个Label,怎么可能占用那么多CPU?全部代码都是可以看到的,望细查你的其它模块的代码。