iOS - 跑马灯、弹幕
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 - 跑马灯、弹幕的更多相关文章
- IOS跑马灯效果,实现文字水平无间断滚动
ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIViewController{ NSTimer ...
- iOS 跑马灯带图片可点击
项目中有个需求,需要以跑马灯的形势滚动展示用户的实时数据,跑马灯需要有用户头像,内容的长度不固定,并且可以点击,滚动效果还要足够流畅,本着不重复造轮子的心理,在网上各种搜索,发现都没法找到满足需求的d ...
- iOS 跑马灯 之 TXScrollLabelView
前言 前段时间在开发一个广播的功能,网上也自己找了一些库,没有发现非常好用的,于是自己抽时间写了一个,在 Github 上发布一天收获六十多个 star,这里首先感谢大家在微博上的转发,使得 TXSc ...
- 【IOS】自定义可点击的多文本跑马灯YFRollingLabel
需求 项目中需要用到跑马灯来仅展示一条消息,长度合适则不滚动,过长则循环滚动. 虽然不是我写的,但看了看代码,是在一个UIView里面放入两个UILabel, 在前一个快结束的时候,另一个显示.然而点 ...
- iOS 学习 - 24 全局跑马灯,支持后台回到前台
思路: 1.创建一个单例 + (instancetype)shareManager { static CCPaomaView *pModel = nil; static dispatch_once_t ...
- iOS swift跑马灯滚动可以点击
跑马灯,从右至左循环滚动显示信息,并且支持点击事件,使用swift4.0语法完成,更加简介,通用性强,布局部分全部使用snpkit 代码: // // HXQMarqueeView.swift // ...
- iOS中跑马灯效果小结
时光过得好快,记忆中刚刚从春节返回没有多久,清明.五一已飞逝而过,眨眼已到盛夏季节.不过还好,济南这两年不算太热,刚开始升温几天,一场及时雨总能让温度保持适宜.为了纪念一下青春的尾巴,也为了能有个健康 ...
- 为 Xamarin.Forms 做个跑马灯控件
前段时间,私下用 Xamarin.Forms 做了个商业项目的演示版.很多被国内App玩坏了的控件/效果,XF上都没有或是找不到对应的实现,没有办法只能亲自上阵写了几个,效果还行,就是有BUG. 这个 ...
- JavaScript小实例-文字跑马灯效果
我们常常能看到显示屏上字体的滚动以及手机弹幕等,下面所示代码就是一个简易的文字跑马灯的效果: <!DOCTYPE html> <html> <head lang=&quo ...
随机推荐
- 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 ...
- 还原JavaScript的真实历史~
问题 ============ JavaScript真的继承自Cmm吗? JavaScript与Java有多少关系? JavaScirpt最初的设计是怎样的?在许多资料,JavaScript的语源被追 ...
- mysql数据库查询优化
上两周一直想办法提高查询速度,取得一点效果,解决了部分问题,记下来以便将来自己查看. 由于公司没有专门的DBA,我自己对mysql数据库也不是很熟悉,而且这个JAVA开发的网络审计系统的管理系统,是经 ...
- System.Net.Http.Formatting的nuget版本冲突问题
已经添加了nuget Microsoft.AspNet.WebApi.Client 调用System.Net.Http.HttpClient.PostAsJsonAsync的时候报如下的错误: C ...
- SMTP 协议系列一
解说一下DOS下telnet命令发送邮件 步骤,以我的163邮箱为例 1.開始-->cmd 进入到dos里面 2.输入telnet smtp.163.com 25 C: \Users \Ad ...
- 【CSWS2014 Summer School】大数据下的游戏营销模式革新-邓大付
大数据下的游戏营销模式革新 邓大付博士腾讯专家工程师 Bio:毕业于华中科技大学,现任腾讯IEG运营部数据中心技术副总监,负责腾讯游戏的数据挖掘相关工作,包括有用户画像,推荐系统,基础算法研究等.主要 ...
- 【Linux】通过SSH修改调整Linux时间和时区
VPS(Virtual Private Server 虚拟专用服务器)技术,将一部服务器分割成多个虚拟专享服务器的一种服务.大多站长喜欢用美国的VPS,而美国的时间和时区和国内不同,那就需要通过SSH ...
- MemSQL学习笔记-类似MySQL的数据库
http://gigaom.com/cloud/ex-facebookers-launch-memsql-to-make-your-database-fly/ -- 多主-从 http://www.m ...
- EXCEPTION-javaBean
CreateTime--2016年11月24日14:29:43Author:Marydon 声明:异常类文章主要是记录了我遇到的异常信息及解决方案,解决方案大部分都是百度解决的,(这里只是针对我遇 ...
- SettingsSVNPlugin
迁移时间:2017年5月20日11:24:50CreateTime--2016年9月18日17:53:20Author:Marydonmyeclipse/eclipse中配置svn插件参考链接:h ...