#import <UIKit/UIKit.h>
@protocol MarqueeControlDelegate <NSObject>
//点击跑马灯回调方法
-(void)selectTitleForIndex:(int)index andTitle:(NSString*)title;
@end
@interface MarqueeControl : UIView
//内容数组
@property(strong ,nonatomic)NSArray *titleArr;
//点击回调
@property(assign ,nonatomic)id<MarqueeControlDelegate> delegate;
//初始化方法
-(instancetype)initWithFrame:(CGRect)frame andContent:(NSArray*)titleArr;
-(void)start;
-(void)stop;
//重新加载跑马灯数据
-(void)resetMarqueeControlView:(NSArray*)titles;
@end
主要的思想就是跑马灯的内容展示在btn上,btn放入数组中,然后修改坐标X,动画中实现左移效果,当第一个btn移出视图,那么第一个btn要放到最后,数组中也是从第一个删除,加到最后
#import "MarqueeControl.h"
#define SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width)
//字体大小
#define WORD_FONT 17
//动画时间
#define ANIMATE_TIME 0.05
//动画延时时间
#define ANIMATE_DELAY 0
//每条信息间隔距离
#define BUTTON_SPACING 20
#define BUTTON_TAG 100
@interface MarqueeControl()
//装载内容按钮数组
@property (strong ,nonatomic)NSMutableArray *titleBtnArr;
//是否在滚动
@property (assign ,nonatomic)BOOL revolve;
@end
@implementation MarqueeControl
//无数据初始化方法
-(instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self initData];
}
return self;
}
//有数据初始化方法
-(instancetype)initWithFrame:(CGRect)frame andContent:(NSArray*)titleArr
{
self = [super initWithFrame:frame];
if (self) {
[self initData];
if (titleArr) {
self.titleArr = titleArr;
[self layoutContentView];
}
}
return self;
}
//初始化滚动数据
-(void)initData{
//这句话的意思就是说,内容是不是只在本视图展示,移出界面是否还展示
self.clipsToBounds = YES;
self.titleBtnArr = [[NSMutableArray alloc]init];
self.revolve = NO;
}
//布局界面
#pragma mark -布局
-(void)layoutContentView
{
//利用UILabel的sizeToFit方法,得到文字长度
UILabel *tempLabel = [UILabel new];
tempLabel.font = [UIFont boldSystemFontOfSize:WORD_FONT];
for(int i=0;i<self.titleArr.count;i++)
{
NSString *title = self.titleArr[i];
tempLabel.text = title;
[tempLabel sizeToFit];
//每一条内容都是一个button展示
UIButton *titleBtn = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, 0, 0)];;
titleBtn.titleLabel.font = [UIFont boldSystemFontOfSize:WORD_FONT];
titleBtn.titleLabel.textAlignment = NSTextAlignmentCenter;
titleBtn.tag = BUTTON_TAG+i;
[titleBtn addTarget:self action:@selector(titleBtnClick:) forControlEvents:UIControlEventTouchUpInside];
if (self.titleArr.count>0 && i > 0) {
UIButton *btn = self.titleBtnArr[i-1];
//btn的frame.x由前个按钮的坐标+间隔,长度由label提供
titleBtn.frame = CGRectMake(btn.frame.origin.x+btn.frame.size.width, 0, tempLabel.frame.size.width+BUTTON_SPACING, self.frame.size.height);
}else{
如果是第一个按钮,就不需要它之前的按钮坐标判断位置了
titleBtn.frame = CGRectMake(0, 0, tempLabel.frame.size.width+BUTTON_SPACING, self.frame.size.height);
}
[titleBtn setTitle:title forState:UIControlStateNormal];
[titleBtn setTitleColor:UIColorFromRGB(0x333333) forState:UIControlStateNormal];
titleBtn.titleLabel.font = [UIFont boldSystemFontOfSize:WORD_FONT];
//添加到页面上
[self addSubview:titleBtn];
//添加到数组中
[self.titleBtnArr addObject:titleBtn];
}
}
//重新加载滚动内容
-(void)resetMarqueeControlView:(NSArray*)titles
{
//先暂停动画
[self stop];
//删除按钮
for(UIButton *btn in self.titleBtnArr)
{
[btn removeFromSuperview];
[btn.layer removeAllAnimations];
}
[self.titleBtnArr removeAllObjects];
//重新加载数据
if (titles) {
self.titleArr = titles;
[self layoutContentView];
}
}
#pragma mark -操作跑马灯事件
//开始动画
-(void)start
{
if (!self.revolve) {
self.revolve = YES;
[self startRevolve];
}
}
//停止动画
-(void)stop{
self.revolve = NO;
}
-(void)startRevolve
{
//UIViewAnimationOptionAllowUserInteraction在动画过程中,允许点击交互
[UIView animateWithDuration:ANIMATE_TIME delay:ANIMATE_DELAY options:UIViewAnimationOptionAllowUserInteraction|UIViewAnimationOptionCurveLinear animations:^{
//执行动画,数组中的所有按钮frame.x坐标往左移动每次-1
for (UIButton *btn in self.titleBtnArr) {
CGRect frame = btn.frame;
frame = CGRectMake(frame.origin.x-1, frame.origin.y, frame.size.width, frame.size.height);
btn.frame = frame;
}
} completion:^(BOOL finished) {
//取第一个按钮
UIButton *btn = self.titleBtnArr[0];
//取最后一个按钮
UIButton *lastBtn = self.titleBtnArr[self.titleBtnArr.count-1];
CGRect frame = btn.frame;
//判断数组中的第一个按钮像左移动,是不是已经移出视图中
if (frame.size.width + frame.origin.x<0) {
//如果最后一个按钮x+width小于当前视图宽度
if (lastBtn.frame.origin.x+lastBtn.frame.size.width<self.frame.size.width) {
//第一个按钮的坐标要放到视图的最右边,然后慢慢左移滑入
frame = CGRectMake(self.frame.size.width, frame.origin.y, frame.size.width, frame.size.height);
}else{
//第一个按钮的坐标排在最后一个按钮的后面,慢慢左移滑入
frame = CGRectMake(lastBtn.frame.origin.x+lastBtn.frame.size.width, frame.origin.y, frame.size.width, frame.size.height);
}
//数组中删除第一个按钮
[self.titleBtnArr removeObjectAtIndex:0];
btn.frame = frame;
//按钮加到最后面,也就是说第一个按钮,左移出了界面,就要放到界面的最后
[self.titleBtnArr addObject:btn];
}
//判断是否继续滚动了
if(self.revolve){
[self startRevolve];
}
}];
}
#pragma mark -代理回调
-(void)titleBtnClick:(UIButton*)sender
{
int index =(int)sender.tag-BUTTON_TAG;
[self.delegate selectTitleForIndex:index andTitle:self.titleArr[index]];
}