1、跑马灯

  • 具体实现代码见 GitHub 源码 QExtension

  • QMarqueeView.h

    	#pragma mark - QMarqueeViewDelegate
    
    	/// 跑马灯内容点击处理协议
    @protocol QMarqueeViewDelegate <NSObject> - (void)didClickContentAtIndex:(NSInteger)index; @end #pragma mark - QMarqueeView /// 跑马灯滚动方向枚举
    typedef NS_ENUM(NSUInteger, QMarqueeViewDirection) {
    QMarqueeViewDirectionUp,
    QMarqueeViewDirectionDown,
    QMarqueeViewDirectionLeft,
    QMarqueeViewDirectionRight
    }; @interface QMarqueeView : UIView /// 显示的文本内容
    @property (nonatomic, strong) NSArray *contentTexts; /// 显示的文本内容颜色,default is redColor
    @property (nonatomic, strong) UIColor *contentTextColor; /// 显示的文本内容字体,default is 15.0
    @property (nonatomic, strong) UIFont *contentTextFont; /// 显示的文本内容对齐方式,default is NSTextAlignmentLeft
    @property (nonatomic, assign) NSTextAlignment contentTextAlign; /// 显示的图标内容,可以为 nil 不显示图标
    @property (nonatomic, strong) UIImage *contentIcon; /// 动画方向,default is QMarqueeViewDirectionUp
    @property (nonatomic, assign) QMarqueeViewDirection animationDirection; /// 动画时间,等于 0 时不滚动
    @property (nonatomic, assign) NSTimeInterval animationDuration; /// 动画停顿时间,default is 1.0 秒
    @property (nonatomic, assign) NSTimeInterval animationDelay; /// 代理
    @property (nonatomic, weak) id<QMarqueeViewDelegate> delegate; /**
    * 开始动画
    */
    - (void)q_startAnimation; /**
    * 创建跑马灯视图控件,开始滚动
    *
    * @param frame 跑马灯对象的 frame
    * @param texts 显示的文本内容
    * @param color 显示的文本内容颜色,default is redColor
    * @param font 显示的文本内容字体,default is 15.0
    * @param align 显示的文本内容对齐方式,default is NSTextAlignmentLeft
    * @param icon 显示的图片内容
    * @param direction 动画方向,default is QMarqueeViewDirectionUp
    * @param duration 动画时间,等于 0 时不滚动
    * @param delay 动画停顿时间,default is 1.0 秒
    * @param target 代理
    *
    * @return 跑马灯视图控件
    */
    + (instancetype)q_marqueeViewWithFrame:(CGRect)frame
    texts:(NSArray *)texts
    color:(nullable UIColor *)color
    font:(nullable UIFont *)font
    align:(NSTextAlignment)align
    icon:(nullable UIImage *)icon
    direction:(QMarqueeViewDirection)direction
    duration:(NSTimeInterval)duartion
    delay:(NSTimeInterval)delay
    target:(nullable id<QMarqueeViewDelegate>)target; @end
  • QMarqueeView.m

    	#define SELF_WIDTH      self.frame.size.width
    #define SELF_HEIGHT self.frame.size.height @interface QMarqueeView () /// 两个 label 循环滚动
    @property (nonatomic, strong) UILabel *firstContentLabel;
    @property (nonatomic, strong) UILabel *secondContentLabel; /// 显示图片的视图
    @property (nonatomic, strong) UIImageView *imageView; /// 当前显示的行
    @property (nonatomic, assign) NSInteger currentIndex; /// 文本内容的起始位置、宽度、高度
    @property (nonatomic, assign) CGFloat contentX;
    @property (nonatomic, assign) CGFloat contentWidth;
    @property (nonatomic, assign) CGFloat contentHeight; @end @implementation QMarqueeView /// 创建跑马灯视图控件,开始滚动
    + (instancetype)q_marqueeViewWithFrame:(CGRect)frame
    texts:(NSArray *)texts
    color:(nullable UIColor *)color
    font:(nullable UIFont *)font
    align:(NSTextAlignment)align
    icon:(nullable UIImage *)icon
    direction:(QMarqueeViewDirection)direction
    duration:(NSTimeInterval)duartion
    delay:(NSTimeInterval)delay
    target:(nullable id<QMarqueeViewDelegate>)target { QMarqueeView *marqueeView = [[self alloc] initWithFrame:frame]; marqueeView.contentTexts = texts;
    marqueeView.contentTextColor = color;
    marqueeView.contentTextFont = font;
    marqueeView.contentTextAlign = align;
    marqueeView.contentIcon = icon;
    marqueeView.animationDirection = direction;
    marqueeView.animationDuration = duartion;
    marqueeView.animationDelay = delay;
    marqueeView.delegate = target; [marqueeView q_startAnimation]; return marqueeView;
    } /// 创建视图控件
    - (void)setupView { // 父视图裁剪
    self.clipsToBounds = YES; // 控件之间的间隔值
    CGFloat margin = 10; // 判断是否有图标
    if (self.contentIcon) { // 添加 Icon 视图
    CGRect iconBackFrame = CGRectMake(0, 0, margin + SELF_HEIGHT, SELF_HEIGHT);
    UIView *iconBackView = [[UIView alloc] initWithFrame:iconBackFrame];
    iconBackView.backgroundColor = [UIColor clearColor];
    [self addSubview:iconBackView]; CGRect iconFrame = CGRectMake(margin, 0, SELF_HEIGHT, SELF_HEIGHT);
    self.imageView = [[UIImageView alloc] initWithFrame:iconFrame];
    self.imageView.backgroundColor = [UIColor clearColor];
    self.imageView.image = self.contentIcon;
    [iconBackView addSubview:self.imageView]; // 计算 Texts 的 frame 值
    self.contentX = margin + SELF_HEIGHT;
    self.contentWidth = SELF_WIDTH - self.contentX - margin; } else { // 计算 Texts 的 frame 值
    self.contentX = margin;
    self.contentWidth = SELF_WIDTH - self.contentX - margin;
    }
    self.contentHeight = SELF_HEIGHT; // 创建第一个 label
    CGRect frame1 = CGRectMake(0, 0, self.contentWidth, self.contentHeight);
    self.firstContentLabel = [[UILabel alloc] initWithFrame:frame1];
    [self setLabel:self.firstContentLabel]; // 创建第二个 label
    if (self.animationDirection <= 1) { CGRect frame2 = CGRectMake(0, SELF_HEIGHT, self.contentWidth, self.contentHeight);
    self.secondContentLabel = [[UILabel alloc] initWithFrame:frame2];
    [self setLabel:self.secondContentLabel];
    }
    } /// 设置 label 属性
    - (void)setLabel:(UILabel *)label { // 设置 label 背景视图
    CGRect frame;
    if (self.contentIcon == nil && self.animationDirection > 1) {
    frame = CGRectMake(0, 0, SELF_WIDTH, self.contentHeight);
    } else {
    frame = CGRectMake(self.contentX, 0, self.contentWidth, self.contentHeight);
    }
    UIView *textBackView = [[UIView alloc] initWithFrame:frame];
    textBackView.backgroundColor = [UIColor clearColor];
    textBackView.clipsToBounds = YES;
    [self addSubview:textBackView]; // 设置默认值
    UIColor *textColor = self.contentTextColor ? : [UIColor redColor];
    UIFont *textFont = self.contentTextFont ? : [UIFont systemFontOfSize:15.0f];
    NSTextAlignment textAlign = self.contentTextAlign ? : NSTextAlignmentLeft; // 设置 label 属性
    label.backgroundColor = [UIColor clearColor];
    label.lineBreakMode = NSLineBreakByTruncatingTail;
    label.textColor = textColor;
    label.font = textFont;
    label.textAlignment = textAlign;
    label.userInteractionEnabled = YES;
    UITapGestureRecognizer *tap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(contentClick)];
    [label addGestureRecognizer:tap1];
    [textBackView addSubview:label];
    } /// 开启滚动动画
    - (void)startLoopAnimation { // 设置默认值
    NSTimeInterval delay = 0;
    NSTimeInterval duration = 0;
    CGFloat currentContentWidth = self.contentWidth; // 设置第一个 label 显示的内容
    self.firstContentLabel.text = self.contentTexts[self.currentIndex]; // 滚动时间为 0 时,停止滚动
    if (0 == self.animationDuration) {
    return;
    } else {
    if (self.animationDirection > 1) { // 左右滚动 // 不停顿
    delay = 0; // 计算文本内容长度
    currentContentWidth = [self.firstContentLabel.text sizeWithAttributes:@{NSFontAttributeName:(self.contentTextFont ? :
    [UIFont systemFontOfSize:15.0f])}].width; duration = self.animationDuration * currentContentWidth / 150; } else { // 垂直滚动 // 动画停顿时间,默认为 1.0 秒
    delay = self.animationDelay ? : 1.0f; duration = self.animationDuration; // 设置第二个 label 显示的内容
    NSInteger secondCurrentIndex = self.currentIndex + 1;
    if (secondCurrentIndex > self.contentTexts.count - 1) {
    secondCurrentIndex = 0;
    }
    self.secondContentLabel.text = self.contentTexts[secondCurrentIndex];
    }
    } CGFloat firstContentLastStartX = 0;
    CGFloat firstContentLastEndX = 0; CGFloat firstContentLastStartY = 0;
    CGFloat firstContentLastEndY = 0;
    CGFloat secondContentLastStartY = 0;
    CGFloat secondContentLastEndY = 0; // 判断滚动方向
    switch (self.animationDirection) { case QMarqueeViewDirectionUp: { firstContentLastStartY = 0;
    firstContentLastEndY = -SELF_HEIGHT; secondContentLastStartY = firstContentLastStartY + SELF_HEIGHT;
    secondContentLastEndY = firstContentLastEndY + SELF_HEIGHT; break;
    } case QMarqueeViewDirectionDown: { firstContentLastStartY = 0;
    firstContentLastEndY = SELF_HEIGHT; secondContentLastStartY = firstContentLastStartY - SELF_HEIGHT;
    secondContentLastEndY = firstContentLastEndY - SELF_HEIGHT; break;
    } case QMarqueeViewDirectionLeft: { firstContentLastStartX = self.contentWidth;
    firstContentLastEndX = -currentContentWidth; break;
    } case QMarqueeViewDirectionRight: { firstContentLastStartX = -currentContentWidth;
    firstContentLastEndX = self.contentWidth; break;
    } default:
    break;
    } // 设置开始时的 frame
    CGRect frame1;
    CGRect frame2;
    if (self.animationDirection > 1) {
    frame1 = CGRectMake(firstContentLastStartX, 0, currentContentWidth, self.contentHeight);
    } else {
    frame1 = CGRectMake(0, firstContentLastStartY, self.contentWidth, self.contentHeight);
    frame2 = CGRectMake(0, secondContentLastStartY, self.contentWidth, self.contentHeight);
    }
    self.firstContentLabel.frame = frame1;
    self.secondContentLabel.frame = frame2; // 开始一次滚动动画
    [UIView beginAnimations:@"" context:nil];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    [UIView setAnimationDuration:duration];
    [UIView setAnimationDelay:delay];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(loopAnimationDidStop:finished:context:)]; // 设置结束时的 frame
    CGRect frame3;
    CGRect frame4;
    if (self.animationDirection > 1) {
    frame3 = CGRectMake(firstContentLastEndX, 0, currentContentWidth, self.contentHeight);
    } else {
    frame3 = CGRectMake(0, firstContentLastEndY, self.contentWidth, self.contentHeight);
    frame4 = CGRectMake(0, secondContentLastEndY, self.contentWidth, self.contentHeight);
    }
    self.firstContentLabel.frame = frame3;
    self.secondContentLabel.frame = frame4; // 结束一次滚动动画
    [UIView commitAnimations];
    } /// 一次动画结束事件响应处理
    - (void)loopAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { self.currentIndex++;
    if (self.currentIndex >= self.contentTexts.count) {
    self.currentIndex = 0;
    } // 重新开启滚动动画
    [self startLoopAnimation];
    } /// 开始滚动
    - (void)q_startAnimation { // 创建视图
    [self setupView]; // 开启动画默认第一条信息
    self.currentIndex = 0; // 开始滚动动画
    [self startLoopAnimation];
    } /// 文本内容点击事件处理
    - (void)contentClick { if ([self.delegate respondsToSelector:@selector(didClickContentAtIndex:)]) {
    [self.delegate didClickContentAtIndex:self.currentIndex];
    }
    } @end
  • 使用

    • 1、初始化

      • QMarqueeView 继承自 UIView, 初始化和 UIView 一样

        	// 创建跑马灯视图控件
        CGRect frame = CGRectMake(0, 50, self.view.bounds.size.width, 30);
        QMarqueeView *marqueeView = [[QMarqueeView alloc] initWithFrame:frame]; // 常规设置,QMarqueeView 继承自 UIView, 设置和 UIView 一样
        marqueeView.layer.cornerRadius = 15;
        marqueeView.layer.masksToBounds = YES;
        marqueeView.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.5];
        [self.view addSubview:marqueeView];
      • 也可以使用类方法一体式创建设置

        	// 创建滚动视图,开始滚动
        CGRect frame = CGRectMake(30, 250, self.view.bounds.size.width - 100, 30);
        QMarqueeView *marqueeView = [QMarqueeView q_marqueeViewWithFrame:frame
        texts:showList
        color:[UIColor whiteColor]
        font:nil
        align:NSTextAlignmentLeft
        icon:[UIImage imageNamed:@"waring1"]
        direction:QMarqueeViewDirectionDown
        duration:1.0
        delay:0
        target:self];
        [self.view addSubview:marqueeView];
    • 2、设置显示的文本内容

      • 文本内容存放到数组中设置

        	// 设置显示的内容
        NSArray *showList = @[@"1. Hello World",
        @"2. 欢迎大家关注哦!",
        @"3. GitHub:QianChia",
        @"4. 新浪微博:QianChia0123",
        @"5. 个人博客:cnblogs.com/QianChia"]; marqueeView.contentTexts = showList;
      • 文本内容可选属性设置,可以设置文本内容的颜色、字体、及对齐方式

        	// 显示的文本内容颜色,default is redColor
        marqueeView.contentTextColor = [UIColor whiteColor]; // 显示的文本内容字体,default is 15.0
        marqueeView.contentTextFont = [UIFont boldSystemFontOfSize:18]; // 显示的文本内容对齐方式,default is NSTextAlignmentLeft
        marqueeView.contentTextAlign = NSTextAlignmentCenter;
    • 3、设置显示的图标内容

      • 除显示文本内容外,还可以可选设置显示左侧图标

        	// 显示的图标内容,可以为 nil 不显示图标
        marqueeView.contentIcon = [UIImage imageNamed:@"waring1"];
    • 4、设置动画时间

      • 动画时间等于 0 时不进行滚动

        	// 设置动画时间
        marqueeView.animationDuration = 5.0;
    • 5、设置动画方向

      • 不设置时默认向上滚动

        	// 设置动画方向,default is QMarqueeViewDirectionUp
        marqueeView.animationDirection = QMarqueeViewDirectionRight;
    • 6、设置动画停顿时间

      • 一次动画滚动完成后可以设置停顿时间,不设置时默认为 1.0 秒

        	// 设置动画停顿时间,default is 1.0 秒
        marqueeView.animationDelay = 2.0;
    • 7、设置点击回调代理

      • 点击显示的内容时可以可选设置响应代理

        	// 设置代理,响应滚动视图点击
        marqueeView.delegate = self;
    • 8、开始滚动动画

      • 添加设置完成后,开启动画

        	// 开始动画
        [marqueeView q_startAnimation];

1.1 垂直滚动

  • 1、垂直滚动,左侧对齐

    	// 创建跑马灯视图控件
    CGRect frame = CGRectMake(0, 50, self.view.bounds.size.width, 30);
    QMarqueeView *marqueeView = [[QMarqueeView alloc] initWithFrame:frame]; // 设置显示的内容
    NSArray *showList = @[@"1. Hello World",
    @"2. 欢迎大家关注哦!",
    @"3. GitHub:QianChia",
    @"4. 新浪微博:QianChia0123",
    @"5. 个人博客:cnblogs.com/QianChia"]; marqueeView.contentTexts = showList;
    marqueeView.contentTextColor = [UIColor whiteColor];
    marqueeView.contentTextFont = [UIFont boldSystemFontOfSize:18]; // 设置动画时间
    marqueeView.animationDuration = 0.2; // 常规设置
    marqueeView.backgroundColor = [UIColor colorWithRed:102/255.0f green:133/255.0f blue:253/255.0f alpha:1];
    [self.view addSubview:marqueeView]; // 开始滚动
    [marqueeView q_startAnimation];
    • 效果

  • 2、垂直滚动,中间对齐

    	// 创建跑马灯视图控件
    CGRect frame = CGRectMake(0, 50, self.view.bounds.size.width, 30);
    QMarqueeView *marqueeView = [[QMarqueeView alloc] initWithFrame:frame]; // 设置显示的内容
    NSArray *showList = @[@"1. Hello World",
    @"2. 欢迎大家关注哦!",
    @"3. GitHub:QianChia",
    @"4. 新浪微博:QianChia0123",
    @"5. 个人博客:cnblogs.com/QianChia"]; marqueeView.contentTexts = showList;
    marqueeView.contentTextColor = [UIColor whiteColor];
    marqueeView.contentTextFont = [UIFont boldSystemFontOfSize:18]; // 设置动画时间
    marqueeView.animationDuration = 0.2; // 设置显示的内容对齐方式
    marqueeView.contentTextAlign = NSTextAlignmentCenter; // 常规设置
    marqueeView.backgroundColor = [UIColor colorWithRed:102/255.0f green:133/255.0f blue:253/255.0f alpha:1];
    [self.view addSubview:marqueeView]; // 开始滚动
    [marqueeView q_startAnimation];
    • 效果

  • 3、垂直滚动,带图标

    	// 创建跑马灯视图控件
    CGRect frame = CGRectMake(30, 150, self.view.bounds.size.width - 150, 30);
    QMarqueeView *marqueeView = [[QMarqueeView alloc] initWithFrame:frame]; // 设置显示的内容
    NSArray *showList = @[@"GitHub:QianChia"];
    marqueeView.contentTexts = showList;
    marqueeView.contentTextColor = [UIColor whiteColor]; // 设置显示的图标
    marqueeView.contentIcon = [UIImage imageNamed:@"waring1"]; // 设置动画时间
    marqueeView.animationDuration = 0.5; // 常规设置
    marqueeView.layer.cornerRadius = 15;
    marqueeView.layer.masksToBounds = YES;
    marqueeView.backgroundColor = [UIColor colorWithRed:102/255.0f green:133/255.0f blue:253/255.0f alpha:1];
    [self.view addSubview:marqueeView]; // 开始滚动
    [marqueeView q_startAnimation];
    • 效果

  • 4、垂直滚动,向下滚动

    	// 创建跑马灯视图控件
    CGRect frame = CGRectMake(30, 200, self.view.bounds.size.width - 150, 30);
    QMarqueeView *marqueeView = [[QMarqueeView alloc] initWithFrame:frame]; // 设置显示的内容
    NSArray *showList = @[@"GitHub:QianChia"];
    marqueeView.contentTexts = showList;
    marqueeView.contentTextColor = [UIColor whiteColor];
    marqueeView.contentIcon = [UIImage imageNamed:@"waring1"]; // 设置动画时间
    marqueeView.animationDuration = 0.5; // 设置动画方向
    marqueeView.animationDirection = QMarqueeViewDirectionDown; // 常规设置
    marqueeView.layer.cornerRadius = 15;
    marqueeView.layer.masksToBounds = YES;
    marqueeView.backgroundColor = [UIColor colorWithRed:102/255.0f green:133/255.0f blue:253/255.0f alpha:1];
    [self.view addSubview:marqueeView]; // 开始滚动
    [marqueeView q_startAnimation];
    • 效果

  • 5、垂直滚动,由类方法创建

    	// 设置显示的内容
    NSArray *showList = @[@"1. Hello World",
    @"2. 欢迎大家关注哦!",
    @"3. GitHub:QianChia",
    @"4. 新浪微博:QianChia0123",
    @"5. 个人博客:cnblogs.com/QianChia"]; // 创建跑马灯视图控件,开始滚动
    CGRect frame = CGRectMake(30, 250, self.view.bounds.size.width - 100, 30);
    QMarqueeView *marqueeView = [QMarqueeView q_marqueeViewWithFrame:frame
    texts:showList
    color:[UIColor whiteColor]
    font:nil
    align:NSTextAlignmentLeft
    icon:[UIImage imageNamed:@"waring1"]
    direction:QMarqueeViewDirectionDown
    duration:1.0
    delay:0
    target:self]; // 常规设置
    marqueeView.layer.cornerRadius = 15;
    marqueeView.layer.masksToBounds = YES;
    marqueeView.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.5];
    [self.view addSubview:marqueeView];
    • 效果

1.2 水平滚动

  • 1、水平滚动,向左滚动

    	// 创建跑马灯视图控件
    CGRect frame = CGRectMake(50, 350, self.view.bounds.size.width - 100, 30);
    QMarqueeView *marqueeView = [[QMarqueeView alloc] initWithFrame:frame]; // 设置显示的内容
    NSArray *showList = @[@"1. Hello World",
    @"2. 欢迎大家关注哦!",
    @"3. GitHub:QianChia",
    @"4. 新浪微博:QianChia0123",
    @"5. 个人博客:cnblogs.com/QianChia"]; marqueeView.contentTexts = showList;
    marqueeView.contentTextColor = [UIColor whiteColor];
    marqueeView.contentTextFont = [UIFont boldSystemFontOfSize:18];
    marqueeView.contentIcon = [UIImage imageNamed:@"waring1"]; // 设置动画时间
    marqueeView.animationDuration = 5.0; // 设置动画方向
    marqueeView.animationDirection = QMarqueeViewDirectionLeft; // 常规设置
    marqueeView.layer.cornerRadius = 15;
    marqueeView.layer.masksToBounds = YES;
    marqueeView.backgroundColor = [UIColor colorWithRed:102/255.0f green:133/255.0f blue:253/255.0f alpha:1];
    [self.view addSubview:marqueeView]; // 开始滚动
    [marqueeView q_startAnimation];
    • 效果

  • 2、水平滚动,向右滚动

    	// 创建跑马灯视图控件
    CGRect frame = CGRectMake(50, 400, self.view.bounds.size.width - 100, 30);
    QMarqueeView *marqueeView = [[QMarqueeView alloc] initWithFrame:frame]; // 设置显示的内容
    NSArray *showList = @[@"1. Hello World",
    @"2. 欢迎大家关注哦!",
    @"3. GitHub:QianChia",
    @"4. 新浪微博:QianChia0123",
    @"5. 个人博客:cnblogs.com/QianChia"]; marqueeView.contentTexts = showList;
    marqueeView.contentTextColor = [UIColor whiteColor];
    marqueeView.contentTextFont = [UIFont boldSystemFontOfSize:18];
    marqueeView.contentIcon = [UIImage imageNamed:@"waring1"]; // 设置动画时间
    marqueeView.animationDuration = 5.0; // 设置动画方向
    marqueeView.animationDirection = QMarqueeViewDirectionRight; // 常规设置
    marqueeView.layer.cornerRadius = 15;
    marqueeView.layer.masksToBounds = YES;
    marqueeView.backgroundColor = [UIColor colorWithRed:102/255.0f green:133/255.0f blue:253/255.0f alpha:1];
    [self.view addSubview:marqueeView]; // 开始滚动
    [marqueeView q_startAnimation];
    • 效果

  • 3、水平滚动,由类方法创建

    	// 设置显示的内容
    NSArray *showList = @[@"1. Hello World",
    @"2. 欢迎大家关注哦!",
    @"3. GitHub:QianChia",
    @"4. 新浪微博:QianChia0123",
    @"5. 个人博客:cnblogs.com/QianChia"]; // 创建跑马灯视图控件,开始滚动
    CGRect frame = CGRectMake(30, 450, self.view.bounds.size.width - 60, 30);
    QMarqueeView *marqueeView = [QMarqueeView q_marqueeViewWithFrame:frame
    texts:showList
    color:nil
    font:nil
    align:0
    icon:[UIImage imageNamed:@"waring2"]
    direction:QMarqueeViewDirectionLeft
    duration:4.0
    delay:0
    target:self]; // 常规设置
    marqueeView.layer.cornerRadius = 15;
    marqueeView.layer.masksToBounds = YES;
    marqueeView.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.5];
    [self.view addSubview:marqueeView];
    • 效果

2、弹幕

  • 具体实现代码见 GitHub 源码 QExtension

  • QBulletScreenView.h

    	#pragma mark - QBulletScreenViewDelegate
    
    	/// 跑马灯内容点击处理协议
    @protocol QBulletScreenViewDelegate <NSObject> - (void)didClickContentAtIndex:(NSInteger)index; @end #pragma mark - QBulletScreenView /// 弹幕滚动方向枚举
    typedef NS_ENUM(NSUInteger, QBulletScreenViewDirection) {
    QBulletScreenViewDirectionUp,
    QBulletScreenViewDirectionDown,
    QBulletScreenViewDirectionLeft,
    QBulletScreenViewDirectionRight
    }; @interface QBulletScreenView : UIView /// 显示的文本内容
    @property (nonatomic, strong) NSArray *contentTexts; /// 显示的文本内容颜色,default is redColor
    @property (nonatomic, strong) UIColor *contentTextColor; /// 显示的文本内容字体,default is 15.0
    @property (nonatomic, strong) UIFont *contentTextFont; /// 显示的图标内容,可以为 nil 不显示图标
    @property (nonatomic, strong) UIImage *contentIcon; /// 动画方向,default is QBulletScreenViewDirectionLeft
    @property (nonatomic, assign) QBulletScreenViewDirection animationDirection; /// 动画时间,等于 0 时不滚动
    @property (nonatomic, assign) NSTimeInterval animationDuration; /// 代理
    @property (nonatomic, weak) id<QBulletScreenViewDelegate> delegate; /**
    * 开始动画
    */
    - (void)q_startAnimation; /**
    * 创建弹幕视图控件
    *
    * @param frame 跑马灯对象的 frame
    * @param texts 显示的文本内容
    * @param color 显示的文本内容颜色,default is redColor
    * @param font 显示的文本内容字体,default is 15.0
    * @param icon 显示的图片内容
    * @param direction 动画方向,default is QMarqueeViewDirectionUp
    * @param duration 动画时间,等于 0 时不滚动
    * @param target 代理
    *
    * @return 弹幕视图控件
    */
    + (instancetype)q_bulletScreenWithFrame:(CGRect)frame
    texts:(NSArray *)texts
    color:(nullable UIColor *)color
    font:(nullable UIFont *)font
    icon:(nullable UIImage *)icon
    direction:(QBulletScreenViewDirection)direction
    duration:(NSTimeInterval)duartion
    target:(nullable id<QBulletScreenViewDelegate>)target; @end
  • QBulletScreenView.m

    	#define SELF_WIDTH      self.frame.size.width
    #define SELF_HEIGHT self.frame.size.height @interface QBulletScreenView () /// label
    @property (nonatomic, strong) UILabel *contentLabel; /// 显示图片的视图
    @property (nonatomic, strong) UIImageView *imageView; /// 当前显示的行
    @property (nonatomic, assign) NSInteger currentIndex; /// 文本内容的起始位置、宽度、高度
    @property (nonatomic, assign) CGFloat contentX;
    @property (nonatomic, assign) CGFloat contentWidth;
    @property (nonatomic, assign) CGFloat contentHeight; /// 弹幕视图的位置、宽度、高度
    @property (nonatomic, assign) CGFloat viewX;
    @property (nonatomic, assign) CGFloat viewY;
    @property (nonatomic, assign) CGFloat viewWidth;
    @property (nonatomic, assign) CGFloat viewHeight; @end @implementation QBulletScreenView /// 创建弹幕视图控件
    + (instancetype)q_bulletScreenWithFrame:(CGRect)frame
    texts:(NSArray *)texts
    color:(nullable UIColor *)color
    font:(nullable UIFont *)font
    icon:(nullable UIImage *)icon
    direction:(QBulletScreenViewDirection)direction
    duration:(NSTimeInterval)duartion
    target:(nullable id<QBulletScreenViewDelegate>)target { QBulletScreenView *bulletScreenView = [[self alloc] initWithFrame:frame]; bulletScreenView.contentTexts = texts;
    bulletScreenView.contentTextColor = color;
    bulletScreenView.contentTextFont = font;
    bulletScreenView.contentIcon = icon;
    bulletScreenView.animationDirection = direction;
    bulletScreenView.animationDuration = duartion;
    bulletScreenView.delegate = target; return bulletScreenView;
    } /// 创建视图控件
    - (void)setupView { // 父视图裁剪
    self.clipsToBounds = YES; // 控件之间的间隔值
    CGFloat margin = 10; // 判断是否有图标
    if (self.contentIcon) { // 添加 Icon 视图
    CGRect iconFrame = CGRectMake(margin, 0, SELF_HEIGHT, SELF_HEIGHT);
    self.imageView = [[UIImageView alloc] initWithFrame:iconFrame];
    self.imageView.backgroundColor = [UIColor clearColor];
    self.imageView.image = self.contentIcon;
    [self addSubview:self.imageView]; // 计算 Texts 的 frame 值
    self.contentX = margin + SELF_HEIGHT;
    self.contentWidth = SELF_WIDTH - self.contentX - margin; } else { // 计算 Texts 的 frame 值
    self.contentX = margin * 2;
    self.contentWidth = SELF_WIDTH - self.contentX - margin;
    }
    self.contentHeight = SELF_HEIGHT;
    self.viewHeight = SELF_HEIGHT; // 设置默认值
    UIColor *textColor = self.contentTextColor ? : [UIColor redColor];
    UIFont *textFont = self.contentTextFont ? : [UIFont systemFontOfSize:15.0f]; // 创建 label
    CGRect frame1 = CGRectMake(self.contentX, 0, self.contentWidth, self.contentHeight);
    self.contentLabel = [[UILabel alloc] initWithFrame:frame1];
    self.contentLabel.backgroundColor = [UIColor clearColor];
    self.contentLabel.lineBreakMode = NSLineBreakByTruncatingTail;
    self.contentLabel.textColor = textColor;
    self.contentLabel.font = textFont;
    self.contentLabel.userInteractionEnabled = YES;
    UITapGestureRecognizer *tap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(contentClick)];
    [self.contentLabel addGestureRecognizer:tap1];
    [self addSubview:self.contentLabel];
    } /// 开启滚动动画
    - (void)startLoopAnimation { // 控件之间的间隔值
    CGFloat margin = 10; // 设置默认值
    NSTimeInterval duration = 0;
    CGFloat currentContentWidth = self.contentWidth; // 设置第一个 label 显示的内容
    self.contentLabel.text = self.contentTexts[self.currentIndex]; // 滚动时间为 0 时,停止滚动
    if (0 == self.animationDuration) {
    return;
    } else { // 计算文本内容长度
    currentContentWidth = [self.contentLabel.text sizeWithAttributes:@{NSFontAttributeName:(self.contentTextFont ? :
    [UIFont systemFontOfSize:15.0f])}].width; CGRect frame = CGRectMake(self.contentX, 0, currentContentWidth, self.contentHeight);
    self.contentLabel.frame = frame; self.viewWidth = self.contentX + currentContentWidth + margin * 2; if (self.animationDirection > 1) { // 左右滚动
    duration = self.animationDuration * currentContentWidth / 150;
    } else { // 垂直滚动
    duration = self.animationDuration;
    }
    } CGFloat viewLastStartX = 0;
    CGFloat viewLastEndX = 0; CGFloat viewLastStartY = 0;
    CGFloat viewLastEndY = 0; // 判断滚动方向
    switch (self.animationDirection) { case QBulletScreenViewDirectionUp: { viewLastStartY = self.superview.bounds.size.height;
    viewLastEndY = -self.viewHeight; break;
    } case QBulletScreenViewDirectionDown: { viewLastStartY = -self.viewHeight;
    viewLastEndY = self.superview.bounds.size.height; break;
    } case QBulletScreenViewDirectionLeft: { viewLastStartX = self.superview.bounds.size.width;
    viewLastEndX = -self.viewWidth; break;
    } case QBulletScreenViewDirectionRight: { viewLastStartX = -self.viewWidth;
    viewLastEndX = self.superview.bounds.size.width; break;
    } default:
    break;
    } self.viewX = self.frame.origin.x;
    self.viewY = self.frame.origin.y; // 设置开始时的 frame
    CGRect frame1;
    if (self.animationDirection > 1) {
    frame1 = CGRectMake(viewLastStartX, self.viewY, self.viewWidth, self.contentHeight);
    } else {
    frame1 = CGRectMake(self.viewX, viewLastStartY, self.viewWidth, self.contentHeight);
    }
    self.frame = frame1; // 开始一次滚动动画
    [UIView beginAnimations:@"" context:nil];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    [UIView setAnimationDuration:duration];
    [UIView setAnimationDelay:0];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(loopAnimationDidStop:finished:context:)]; // 设置结束时的 frame
    CGRect frame2;
    if (self.animationDirection > 1) {
    frame2 = CGRectMake(viewLastEndX, self.viewY, self.viewWidth, self.contentHeight);
    } else {
    frame2 = CGRectMake(self.viewX, viewLastEndY, self.viewWidth, self.contentHeight);
    }
    self.frame = frame2; // 结束一次滚动动画
    [UIView commitAnimations];
    } /// 一次动画结束事件响应处理
    - (void)loopAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context { self.currentIndex++;
    if (self.currentIndex >= self.contentTexts.count) {
    self.currentIndex = 0;
    } // 重新开启滚动动画
    [self startLoopAnimation];
    } /// 开始滚动
    - (void)q_startAnimation { // 创建视图
    [self setupView]; // 开启动画默认第一条信息
    self.currentIndex = 0; // 开始滚动动画
    [self startLoopAnimation];
    } /// 文本内容点击事件处理
    - (void)contentClick { if ([self.delegate respondsToSelector:@selector(didClickContentAtIndex:)]) {
    [self.delegate didClickContentAtIndex:self.currentIndex];
    }
    } @end
  • 使用

    • 1、初始化

      • QBulletScreenView 继承自 UIView, 初始化和 UIView 一样

        	// 创建弹幕视图控件
        CGRect frame = CGRectMake(0, 100, 0, 30);
        QBulletScreenView *bulletScreenView = [[QBulletScreenView alloc] initWithFrame:frame]; // 常规设置,QBulletScreenView 继承自 UIView, 设置和 UIView 一样
        bulletScreenView.layer.cornerRadius = 15;
        bulletScreenView.layer.masksToBounds = YES;
        bulletScreenView.backgroundColor = [[UIColor grayColor] colorWithAlphaComponent:0.5];
        [self.view addSubview:bulletScreenView];
      • 也可以使用类方法一体式创建设置

        	// 创建弹幕视图控件,开始滚动
        CGRect frame = CGRectMake(0, 100, 0, 30);
        QBulletScreenView *bulletScreenView = [QBulletScreenView q_bulletScreenWithFrame:frame
        texts:showList
        color:[UIColor whiteColor]
        font:nil
        icon:[UIImage imageNamed:@"waring1"]
        direction:QBulletScreenViewDirectionLeft
        duration:5.0
        target:nil];
        [self.view addSubview:bulletScreenView];
    • 2、设置显示的文本内容

      • 文本内容存放到数组中设置

        	// 设置显示的内容
        NSArray *showList = @[@"1. Hello World",
        @"2. 欢迎大家关注哦!",
        @"3. GitHub:QianChia",
        @"4. 新浪微博:QianChia0123",
        @"5. 个人博客:cnblogs.com/QianChia"]; bulletScreenView.contentTexts = showList;
      • 文本内容可选属性设置,可以设置文本内容的颜色、字体

        	// 显示的文本内容颜色,default is redColor
        bulletScreenView.contentTextColor = [UIColor whiteColor]; // 显示的文本内容字体,default is 15.0
        bulletScreenView.contentTextFont = [UIFont boldSystemFontOfSize:18];
    • 3、设置显示的图标内容

      • 除显示文本内容外,还可以可选设置显示左侧图标

        	// 显示的图标内容,可以为 nil 不显示图标
        bulletScreenView.contentIcon = [UIImage imageNamed:@"waring1"];
    • 4、设置动画时间

      • 动画时间等于 0 时不进行滚动

        	// 设置动画时间
        bulletScreenView.animationDuration = 5.0;
    • 5、设置动画方向

      • 不设置时默认向上滚动

        	// 设置动画方向,default is QBulletScreenViewDirectionUp
        bulletScreenView.animationDirection = QBulletScreenViewDirectionLeft;
    • 6、设置点击回调代理

      • 点击显示的内容时可以可选设置响应代理

        	// 设置代理,响应滚动视图点击
        bulletScreenView.delegate = self;
    • 7、开始滚动动画

      • 添加设置完成后,开启动画

        	// 开始动画
        [bulletScreenView q_startAnimation];

2.1 水平向左移动

  • 水平向左移动

    	// 创建弹幕视图控件
    CGRect frame = CGRectMake(0, 100, 0, 30); // x, width 设置无效
    QBulletScreenView *bulletScreenView = [[QBulletScreenView alloc] initWithFrame:frame]; // 设置显示的内容
    NSArray *showList = @[@"1. Hello World",
    @"2. 欢迎大家关注哦!",
    @"3. GitHub:QianChia",
    @"4. 新浪微博:QianChia0123",
    @"5. 个人博客:cnblogs.com/QianChia"]; bulletScreenView.contentTexts = showList;
    bulletScreenView.contentTextColor = [UIColor whiteColor];
    bulletScreenView.contentTextFont = [UIFont boldSystemFontOfSize:18];
    bulletScreenView.contentIcon = [UIImage imageNamed:@"waring1"]; // 设置动画时间
    bulletScreenView.animationDuration = 5.0; // 设置动画方向
    bulletScreenView.animationDirection = QBulletScreenViewDirectionLeft; // 常规设置
    bulletScreenView.layer.cornerRadius = 15;
    bulletScreenView.layer.masksToBounds = YES;
    bulletScreenView.backgroundColor = [UIColor colorWithRed:102/255.0f green:133/255.0f blue:253/255.0f alpha:1];
    [self.view addSubview:bulletScreenView]; // 开始滚动
    [bulletScreenView q_startAnimation];
    • 效果

2.2 水平向右移动

  • 水平向右移动

    	// 设置显示的内容
    NSArray *showList = @[@"1. Hello World",
    @"2. 欢迎大家关注哦!",
    @"3. GitHub:QianChia",
    @"4. 新浪微博:QianChia0123",
    @"5. 个人博客:cnblogs.com/QianChia"]; // 创建弹幕视图控件
    CGRect frame = CGRectMake(0, 200, 0, 30); // x, width 设置无效
    QBulletScreenView *bulletScreenView = [QBulletScreenView q_bulletScreenWithFrame:frame
    texts:showList
    color:[UIColor whiteColor]
    font:nil
    icon:[UIImage imageNamed:@"waring1"]
    direction:QBulletScreenViewDirectionRight
    duration:5.0
    target:nil]; // 常规设置
    bulletScreenView.layer.cornerRadius = 15;
    bulletScreenView.layer.masksToBounds = YES;
    bulletScreenView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
    [self.view addSubview:bulletScreenView]; // 开始滚动
    [bulletScreenView q_startAnimation];
    • 效果

2.3 水平向上移动

  • 水平向上移动

    	// 创建弹幕视图控件
    CGRect frame = CGRectMake(10, 0, 0, 30); // y, width 设置无效
    QBulletScreenView *bulletScreenView = [[QBulletScreenView alloc] initWithFrame:frame]; // 设置显示的内容
    NSArray *showList = @[@"1. Hello World",
    @"2. 欢迎大家关注哦!",
    @"3. GitHub:QianChia",
    @"4. 新浪微博:QianChia0123",
    @"5. 个人博客:cnblogs.com/QianChia"]; bulletScreenView.contentTexts = showList;
    bulletScreenView.contentTextColor = [UIColor whiteColor];
    bulletScreenView.contentTextFont = [UIFont boldSystemFontOfSize:18];
    bulletScreenView.contentIcon = [UIImage imageNamed:@"waring1"]; // 设置动画时间
    bulletScreenView.animationDuration = 2.0; // 设置动画方向
    bulletScreenView.animationDirection = QBulletScreenViewDirectionUp; // 常规设置
    bulletScreenView.layer.cornerRadius = 15;
    bulletScreenView.layer.masksToBounds = YES;
    bulletScreenView.backgroundColor = [UIColor colorWithRed:102/255.0f green:133/255.0f blue:253/255.0f alpha:1];
    [backView addSubview:bulletScreenView]; // 开始滚动
    [bulletScreenView q_startAnimation];
    • 效果

2.4 水平向下移动

  • 水平向下移动

    	// 设置显示的内容
    NSArray *showList = @[@"1. Hello World",
    @"2. 欢迎大家关注哦!",
    @"3. GitHub:QianChia",
    @"4. 新浪微博:QianChia0123",
    @"5. 个人博客:cnblogs.com/QianChia"]; // 创建弹幕视图控件
    CGRect frame = CGRectMake(10, 0, 0, 30); // y, width 设置无效
    QBulletScreenView *bulletScreenView = [QBulletScreenView q_bulletScreenWithFrame:frame
    texts:showList
    color:[UIColor whiteColor]
    font:[UIFont boldSystemFontOfSize:18]
    icon:[UIImage imageNamed:@"waring1"]
    direction:QBulletScreenViewDirectionDown
    duration:2.0
    target:nil]; // 常规设置
    bulletScreenView.layer.cornerRadius = 15;
    bulletScreenView.layer.masksToBounds = YES;
    bulletScreenView.backgroundColor = [UIColor colorWithRed:102/255.0f green:133/255.0f blue:253/255.0f alpha:1];
    [backView addSubview:bulletScreenView]; // 开始滚动
    [bulletScreenView q_startAnimation];
    • 效果

iOS - 跑马灯、弹幕的更多相关文章

  1. IOS跑马灯效果,实现文字水平无间断滚动

    ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIViewController{ NSTimer ...

  2. iOS 跑马灯带图片可点击

    项目中有个需求,需要以跑马灯的形势滚动展示用户的实时数据,跑马灯需要有用户头像,内容的长度不固定,并且可以点击,滚动效果还要足够流畅,本着不重复造轮子的心理,在网上各种搜索,发现都没法找到满足需求的d ...

  3. iOS 跑马灯 之 TXScrollLabelView

    前言 前段时间在开发一个广播的功能,网上也自己找了一些库,没有发现非常好用的,于是自己抽时间写了一个,在 Github 上发布一天收获六十多个 star,这里首先感谢大家在微博上的转发,使得 TXSc ...

  4. 【IOS】自定义可点击的多文本跑马灯YFRollingLabel

    需求 项目中需要用到跑马灯来仅展示一条消息,长度合适则不滚动,过长则循环滚动. 虽然不是我写的,但看了看代码,是在一个UIView里面放入两个UILabel, 在前一个快结束的时候,另一个显示.然而点 ...

  5. iOS 学习 - 24 全局跑马灯,支持后台回到前台

    思路: 1.创建一个单例 + (instancetype)shareManager { static CCPaomaView *pModel = nil; static dispatch_once_t ...

  6. iOS swift跑马灯滚动可以点击

    跑马灯,从右至左循环滚动显示信息,并且支持点击事件,使用swift4.0语法完成,更加简介,通用性强,布局部分全部使用snpkit 代码: // // HXQMarqueeView.swift // ...

  7. iOS中跑马灯效果小结

    时光过得好快,记忆中刚刚从春节返回没有多久,清明.五一已飞逝而过,眨眼已到盛夏季节.不过还好,济南这两年不算太热,刚开始升温几天,一场及时雨总能让温度保持适宜.为了纪念一下青春的尾巴,也为了能有个健康 ...

  8. 为 Xamarin.Forms 做个跑马灯控件

    前段时间,私下用 Xamarin.Forms 做了个商业项目的演示版.很多被国内App玩坏了的控件/效果,XF上都没有或是找不到对应的实现,没有办法只能亲自上阵写了几个,效果还行,就是有BUG. 这个 ...

  9. JavaScript小实例-文字跑马灯效果

    我们常常能看到显示屏上字体的滚动以及手机弹幕等,下面所示代码就是一个简易的文字跑马灯的效果: <!DOCTYPE html> <html> <head lang=&quo ...

随机推荐

  1. @JVM垃圾回收调优方法

    JVM调优工具 Jconsole,jProfile,VisualVM Jconsole:jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用.对垃圾回收算法有很详细的跟踪. JProfiler: ...

  2. Data Binding MVVM 数据绑定 总结

    示例代码:https://github.com/baiqiantao/DataBindingTest 参考:精通Android Data Binding    Android Data Binding ...

  3. python3 操作sqlSever

    相关代码如下: #coding =utf-8 import os import pyodbc import time class SqlDb: def __init__(self, server='D ...

  4. 输错密码?这个 sudo 会“嘲讽”你

    导读 你在 Linux 终端中会有很多的乐趣.我今天要讲的不是在终端中跑火车.我今天要讲的技巧可以放松你的心情.你学习过如何在命令行中增加 sudo 命令的超时,今天的文章中,我会向你展示如何让 su ...

  5. 【转】十个经典的C开源项目代码

    原文: http://blog.51cto.com/chinalx1/2143904 --------------------------------------------------------- ...

  6. 新浪微博SSO登陆机制(转载)

    原文地址: http://www.cnblogs.com/AloneSword/p/3840548.html 最近在使用sina微博时,经常性交替使用 weibo.com 和 t.sina.cm.cn ...

  7. Linux软件安装方法

    常用的两种软件安装方法: 1.RPM软件安装 rpm -qi 软件名 查询 rpm -ivh *.rpm 安装 rpm -e 软件名 卸载 系统自带的一些rpm包在系统镜像的Server文件夹里,需要 ...

  8. 与AQS有关的并发类

    ReetrantLock与Condition: 參考 在java.util.concurrent包中.有两个非常特殊的工具类.Condition和ReentrantLock,使用过的人都知道,Reen ...

  9. The Web Sessions List

    The Web Sessions list contains the list of HTTP Requests that are sent by your computer. You can res ...

  10. CSS实现水平垂直居中方式

    1.定位 核心代码实现请看示例代码中的注释: <!DOCTYPE html> <html lang="zh"> <head> <meta ...