iOS开发造小轮子 | 跑马灯

作者: 无夜之星辰 | 来源:发表于2017-08-22 16:43 被阅读1229次
IU大法

效果

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

效果.gif

思路

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

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

代码

代码没亮点,关键是思路

@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

需求变了。。。

今天产品那边要求能展示多条信息,并且一条信息跑完后再接着跑另一条信息。。。
我表示早已习以为常,然后10秒之内做出响应:
1.既然是多条信息,那数据源肯定从原来的string变成了array。

/** 跑马灯展示的文本数组 */
@property (nonatomic, strong) NSArray *marqueeTextArray;

2.跑完一条信息后跑下一条,跑完所有信息后又从第一条开始跑

/** 改变label位置 */
- (void)refreshMarqueeLabelFrame {
    static int i = 0;
    _marqueeLabel.maxX -= 0.3;
    if (_marqueeLabel.maxX <= 0) { // 当前信息跑完
        i ++;
        _marqueeLabel.x = self.width - 41 - 38; // 回到最右边
        // 取模是关键
        [self setMarqueeText:_marqueeTextArray[i % self.marqueeTextArray.count]];
    }
}

详情可参考demo

需求变更后的demo

上面演示的demo


2017年9月11日更新

将NSTimer换为CADisplayLink(每秒60次)。
注:在模拟器上运行看起有点卡,但真机上很流畅。😎

相关文章

  • iOS开发造小轮子 | 跑马灯

    效果 实际项目中很常见的效果,如下: 思路 让label的宽度自适应内容,然后放到一个背景view上,背景view...

  • iOS开发造小轮子 | loading view

    背景 看简书APP,发现当网络不是很好,它的banner数据没有加载出来的时候,banner中有一个indicat...

  • 2019-11-30

    AVAudioEngine 网络音频播放,下载,解码,播放和滤镜 iOS 音频播放器开发,学习造轮子: 用 AVA...

  • 【springboot+easypoi】一行代码搞定excel导

    我们不造轮子,只是轮子的搬运工。(其实最好是造轮子,造比别人好的轮子) 开发中经常会遇到excel的处理,导入导出...

  • easypoi结合spring-boot 快速使用

    我们不造轮子,只是轮子的搬运工。(其实最好是造轮子,造比别人好的轮子) 开发中经常会遇到excel的处理,导入导出...

  • 好用的跑马灯library库

    1,一个好用的跑马灯library库: 开发当中好用的开源库能帮程序员省很多时间,省得自己造轮子,所以有好用的...

  • iOS开发造轮子 | Loading图

    造这个轮子的原因 几乎每个app都有loading图,虽然有SVProgressHUD和MBProgressHUD...

  • iOS 中 常用的第三方库 (转载)

    轮子图 现在对于我们 iOS 开发来说,基本上说不可能不使用第三方轮子啦,毕竟没那么多时间,而且自己造的轮子往往想...

  • ios常用第三方学习记录

    轮子图 现在对于我们 iOS 开发来说,基本上说不可能不使用第三方轮子啦,毕竟没那么多时间,而且自己造的轮子往往想...

  • iOS 中 常用的第三方库 (转载)

    轮子图 现在对于我们 iOS 开发来说,基本上说不可能不使用第三方轮子啦,毕竟没那么多时间,而且自己造的轮子往往想...

网友评论

本文标题:iOS开发造小轮子 | 跑马灯

本文链接:https://www.haomeiwen.com/subject/lvlldxtx.html