效果圖

開始上代碼
滾動字幕的原理是用timer定時器間隔一定的時間來驅動scrollView上的內容偏移,來實現滾動的效果,原理比較簡單,關鍵是有些細節需要處理好,實現流暢效果的同時要考慮到性能優化
這裡是.h文件的接口方法及屬性,可適應大部分自定義場景
/*初始化*/ -(instancetype)initWithFrame:(CGRect)frame textArray:(NSArray *)textArray colorArray:(NSArray *)textColorArray; //滾動字幕數組 @property(nonatomic,strong) NSArray<NSString *> *textArray; //字幕顏色數組 @property(nonatomic,strong) NSArray<UIColor *> *textColorArray; //字幕背景顏色 @property(nonatomic,strong) UIColor *backgroundColorOfCanvas; //標簽背景圖片 @property(nonatomic,strong) UIImage *backgroundImageOfCanvas; //字體大小 @property(nonatomic,assign) CGFloat fontOfSize; //定時器 @property(nonatomic,strong) NSTimer *timer;
實現滾動字幕的思路和無限輪播圖相似,這裡用了一點小技巧即可實現字幕的收尾連續相接:將同樣的字幕內容復制一份拼接到後面就可以了,當字幕的scrollView滾動到復制的那份內容開頭時,將contentOffset偏移量設置到原始內容的開頭,這樣就可以實現無縫的連續循環滾動了
#pragma mark - 創建scrollView內容
-(void)createContentOfScrollView{
//創建contentView
self.contentSize=CGSizeMake(0, self.bounds.size.height);
//偏移量初值設為0
self.contentOffset=CGPointMake(0, 0);
//關閉指示條
self.showsHorizontalScrollIndicator=NO;
//創建label
CGFloat labelY=0;
CGFloat labelW=200;
CGFloat labelH=self.bounds.size.height;
//添加兩次一樣的內容,無限循環使用
for (int j=0; j<2;j++ ) {
for (int i=0; i<self.textArray.count; i++) {
UILabel *textLabel=[[UILabel alloc] initWithFrame:CGRectMake(self.contentSize.width, labelY, labelW, labelH)];
//******標簽背景******
UIImageView *labelBackGroundView=[[UIImageView alloc] initWithFrame:textLabel.frame];
//標簽背景圖片
labelBackGroundView.image=self.backgroundImageOfCanvas;
//*****label文字******
if (i<self.textArray.count) {
textLabel.text=self.textArray[i];
}else{
textLabel.text=@"----";
}
//label文字顏色(判斷文字顏色數組是否存有對應的顏色,沒有則使用默認顏色)
if (i<self.textColorArray.count) {
textLabel.textColor=self.textColorArray[i];
}else{
//默認顏色
textLabel.textColor=[UIColor blackColor];
}
//******字體大小********
textLabel.font=[UIFont systemFontOfSize:self.fontOfSize];
//label標簽tag值
textLabel.tag=LABEL_TAG_INIT + i + 100 * j;
//每創建一個label在contenSize上加上一個label的寬度
self.contentSize=CGSizeMake(self.contentSize.width+labelW, self.bounds.size.height);
[self addSubview:labelBackGroundView];
[self addSubview:textLabel];
}
}
}
這裡注意定時器timer的使用,要將timer加入到runloop裡,注意是CommonModes,如果用defaultModes的話就會出現卡頓(與滑動等事件處於同一runLoop,系統會優先響應滑動)
小tips:定時器是可以暫停的
NSTimer 系統是沒有提供暫停的方法的,方法列表中只提供了-fire(啟動) 和 -invalidate(廢除)兩個方法,invalidate後是完全廢除不可再重啟
但是這裡有個@property (copy) NSDate *fireDate的屬性,我們可以借助這個屬性來實現定時器的暫停和重啟
//立即啟動定時器 [timer setFireDate:[NSDate date]]; //暫停定時器 [timer setFireDate:[NSDate distantFuture]];
是不是有種很奇妙的感覺,這裡利用定時器的啟動時間屬性巧妙的達到了暫停和重啟的目的
//************自動滾動timer************ NSTimer *timer=[NSTimer scheduledTimerWithTimeInterval:SCROLL_TIME_INTERVAL target:self selector:@selector(autoScroll) userInfo:nil repeats:YES]; [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; //立即啟動定時器 [timer setFireDate:[NSDate date]]; self.timer=timer;
這裡是定時器驅動scrollView滾動的方法
這裡注意了如果要達到字幕連續滾動不斷幀的效果的話,timer調用需要非常頻繁(1秒調用10次以上),此時再看看CPU使用率.瞬間飙升了20%左右,雖然還在能接受的范圍,但在這種小地方耗費CPU顯然不劃算
解決方法:給個動畫過渡就好了嘛,UIView animateWithDuration輕松應付,過渡很流暢,世界也瞬間安靜了。
後遺症:用動畫過渡唯一的問題就是,控制器跳轉後再回來的話,動畫會直接結束跳到尾幀,細心的用戶會發覺這奇怪的地方,這就只有在性能和效果之間調和一下取最優解了
//滾動時間間隔 #define SCROLL_TIME_INTERVAL 3 //每次滾動距離 #define SCROLL_DISTANCE 100
//自動滾動
- (void)autoScroll{
//滾動速度
CGFloat offSet=SCROLL_DISTANCE;
//若果字幕滾動到第二部分重復的部分則把偏移置0,設為第一部分,實現無限循環
if (self.contentOffset.x>=self.contentSize.width / 2) {
self.contentOffset=CGPointMake(0, 0);
}
//切割每次動畫滾動距離
[UIView animateWithDuration:SCROLL_TIME_INTERVAL delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
self.contentOffset=CGPointMake(self.contentOffset.x+offSet, self.contentOffset.y);
} completion:nil];
}
總結
好了,以上就是這篇文章的全部內容了,親們有什麼意見和問題記得及時反饋哦,希望這篇文章的內容對大家的學習或者工作帶來一定的幫助。