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. SQL Server AlwaysOn Setup Step-By-Step Guide

    Step-By-Step: Creating a SQL Server 2012 AlwaysOn Availability Group http://blogs.technet.com/b/cani ...

  2. 还原JavaScript的真实历史~

    问题 ============ JavaScript真的继承自Cmm吗? JavaScript与Java有多少关系? JavaScirpt最初的设计是怎样的?在许多资料,JavaScript的语源被追 ...

  3. mysql数据库查询优化

    上两周一直想办法提高查询速度,取得一点效果,解决了部分问题,记下来以便将来自己查看. 由于公司没有专门的DBA,我自己对mysql数据库也不是很熟悉,而且这个JAVA开发的网络审计系统的管理系统,是经 ...

  4. System.Net.Http.Formatting的nuget版本冲突问题

      已经添加了nuget Microsoft.AspNet.WebApi.Client 调用System.Net.Http.HttpClient.PostAsJsonAsync的时候报如下的错误: C ...

  5. SMTP 协议系列一

    解说一下DOS下telnet命令发送邮件 步骤,以我的163邮箱为例 1.開始-->cmd 进入到dos里面 2.输入telnet  smtp.163.com  25 C: \Users \Ad ...

  6. 【CSWS2014 Summer School】大数据下的游戏营销模式革新-邓大付

    大数据下的游戏营销模式革新 邓大付博士腾讯专家工程师 Bio:毕业于华中科技大学,现任腾讯IEG运营部数据中心技术副总监,负责腾讯游戏的数据挖掘相关工作,包括有用户画像,推荐系统,基础算法研究等.主要 ...

  7. 【Linux】通过SSH修改调整Linux时间和时区

    VPS(Virtual Private Server 虚拟专用服务器)技术,将一部服务器分割成多个虚拟专享服务器的一种服务.大多站长喜欢用美国的VPS,而美国的时间和时区和国内不同,那就需要通过SSH ...

  8. MemSQL学习笔记-类似MySQL的数据库

    http://gigaom.com/cloud/ex-facebookers-launch-memsql-to-make-your-database-fly/ -- 多主-从 http://www.m ...

  9. EXCEPTION-javaBean

      CreateTime--2016年11月24日14:29:43Author:Marydon 声明:异常类文章主要是记录了我遇到的异常信息及解决方案,解决方案大部分都是百度解决的,(这里只是针对我遇 ...

  10. SettingsSVNPlugin

      迁移时间:2017年5月20日11:24:50CreateTime--2016年9月18日17:53:20Author:Marydonmyeclipse/eclipse中配置svn插件参考链接:h ...