iOS开发UI篇 —— 跑马灯效果AutoLabel简介
核心思想
1、通过UIView 开始动画[UIView beginAnimations:@"scroll" context:nil];到提交动画 [UIView commitAnimations]; 来实现动画效果,在这代码之间实现要做动画的效果,中间可以设置动画的速度,是否匀速及监听。
2、通过设置偏移量来实现动画效果,必须是滚动文字label超过父视图才能滚动。
3、当完成一遍动画后,判断动画是否完成及滚动文字宽度是否大于父视图(理论上是大于的,要不怎么会进入代理方法),添加一个定时器实现继续滚动,在这里实现停动效果。
4、放两个label,并设置一定间距,这样可以实现循环滚动的效果,通过数组创建UILabel *_label[2],当为向左时,初始位置是0,0 ;终点位置是第一个label的宽度+间距。
5、核心代码
5.1 UIView beginAnimations的动画
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 | - ( void )scroll{ //删除之前的动画,一定要加,否则外部将不能设置速度、间距及外部变量 [self.layer removeAllAnimations]; //初始位置 if (_dirtionType == DirtionTypeLeft) { self.contentOffset = CGPointMake(0, 0); } else if (_dirtionType == DirtionTypeRight){ self.contentOffset = CGPointMake(_label[0].frame.size.width+_labelBetweenGap, 0); } //开始动画 [UIView beginAnimations: @"scroll" context:nil]; //动画设置参数,代理,匀速,速度等 [UIView setAnimationDelegate:self]; [UIView setAnimationCurve:UIViewAnimationCurveLinear]; [UIView setAnimationDuration:_label[0].frame.size.width/_speed]; [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)]; //animations //终点位置 if (_dirtionType == DirtionTypeLeft) { self.contentOffset = CGPointMake(_label[0].frame.size.width+_labelBetweenGap, 0); } else if (_dirtionType == DirtionTypeRight){ self.contentOffset = CGPointMake(0, 0); } //完成动画 [UIView commitAnimations]; } //动画完成调用 - ( void )animationDidStop:(NSString *)animationID finished:(NSNumber *)finish context:(NSString *)context{ //动画ID animationID,也就是上面scroll,可以设置多个动画,这个animationID用来判断不同动画,finish.integerValue,如果为0时表示未完成,为1时表示已完成 if (finish.integerValue == 1 && _label[0].frame.size.width > self.frame.size.width) { //pause time,动画完成时,添加定时器,设置停留时间再滚动 [NSTimer scheduledTimerWithTimeInterval:_pauseTime target:self selector:@selector(scroll) userInfo:nil repeats:NO]; } } |
5.2 重新布局,设置滚动位置及决定是否可以滚动
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 | - ( void )rejustlabels{ //set labels frame 及self contentsize和is scroll CGFloat offset = 0.0f; for (NSInteger i = 0; i < NumLabels; i++) { [_label[i] sizeToFit]; CGPoint center = _label[i].center; center.y = self.center.y - self.frame.origin.y; _label[i].center = center; CGRect frame = _label[i].frame; frame.origin.x = offset; _label[i].frame = frame; //每个label x的位置 offset += _label[i].frame.size.width+_labelBetweenGap; } CGSize size; size.width = _label[0].frame.size.width+self.frame.size.width+_labelBetweenGap; size.height = self.frame.size.height; self.contentSize = size; //判断是否能滚动 if (_label[0].frame.size.width > self.frame.size.width) { //show lab for (NSInteger i = 1; i <NumLabels; i++) { _label[i].hidden = NO; } [self scroll]; } else { //如果不能滚动,重新设置x的位置 for (NSInteger i = 1;i < NumLabels; i++) { _label[i].hidden = YES; } CGPoint center = _label[0].center; center.x = self.center.x - self.frame.origin.x; _label[0].center = center; } } |
5.3 当有文字时不能重新布局等操作,因为会抖动
1 2 3 4 5 6 7 8 9 10 11 12 13 | - ( void )setText:(NSString *)text{ //如果文字等于当前label的文字,判断是否大于父视图宽度,决定是否滚动,可以滚动,设置滚动,并返回 if ([text isEqualToString:_label[0].text]) { if (_label[0].frame.size.width > self.frame.size.width) { [self scroll]; } return ; } for (NSInteger i = 0; i< NumLabels; i++) { _label[i].text = text; } [self rejustlabels]; } |
代码github地址:https://github.com/TheYouth/STRMarquee
将来的自己,会感谢现在不放弃的自己!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现