iOS黑科技【動畫特效篇】第三期
這一期帶來一款應(yīng)用非常實(shí)用的控件扛芽,滾動字幕擒滑,可以應(yīng)用在新聞腐晾、財經(jīng)、聊天等各類APP上丐一,B格瞬間提升了一個檔次有木有
話不多說藻糖,github走一波,已封裝可直接只用库车,留有一個便捷初始方法及各種屬性接口
https://github.com/XMDashen/XMScrollCanvas.git
順便給個星哦愤估!(*  ̄3)(ε ̄ *)
開始上代碼
滾動字幕的原理是用timer定時器間隔一定的時間來驅(qū)動scrollView上的內(nèi)容偏移寒随,來實(shí)現(xiàn)滾動的效果狮含,原理比較簡單剩晴,關(guān)鍵是有些細(xì)節(jié)需要處理好,實(shí)現(xiàn)流暢效果的同時要考慮到性能優(yōu)化
這里是.h文件的接口方法及屬性珍坊,可適應(yīng)大部分自定義場景
/*初始化*/
-(instancetype)initWithFrame:(CGRect)frame textArray:(NSArray *)textArray colorArray:(NSArray *)textColorArray;
//滾動字幕數(shù)組
@property(nonatomic,strong) NSArray<NSString *> *textArray;
//字幕顏色數(shù)組
@property(nonatomic,strong) NSArray<UIColor *> *textColorArray;
//字幕背景顏色
@property(nonatomic,strong) UIColor *backgroundColorOfCanvas;
//標(biāo)簽背景圖片
@property(nonatomic,strong) UIImage *backgroundImageOfCanvas;
//字體大小
@property(nonatomic,assign) CGFloat fontOfSize;
//定時器
@property(nonatomic,strong) NSTimer *timer;
實(shí)現(xiàn)滾動字幕的思路和無限輪播圖相似牺勾,這里用了一點(diǎn)小技巧即可實(shí)現(xiàn)字幕的收尾連續(xù)相接:將同樣的字幕內(nèi)容復(fù)制一份拼接到后面就可以了,當(dāng)字幕的scrollView滾動到復(fù)制的那份內(nèi)容開頭時阵漏,將contentOffset偏移量設(shè)置到原始內(nèi)容的開頭禽最,這樣就可以實(shí)現(xiàn)無縫的連續(xù)循環(huán)滾動了O(∩_∩)O
#pragma mark - 創(chuàng)建scrollView內(nèi)容
-(void)createContentOfScrollView{
//創(chuàng)建contentView
self.contentSize=CGSizeMake(0, self.bounds.size.height);
//偏移量初值設(shè)為0
self.contentOffset=CGPointMake(0, 0);
//關(guān)閉指示條
self.showsHorizontalScrollIndicator=NO;
//創(chuàng)建label
CGFloat labelY=0;
CGFloat labelW=200;
CGFloat labelH=self.bounds.size.height;
//添加兩次一樣的內(nèi)容腺怯,無限循環(huán)使用
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)];
//******標(biāo)簽背景******
UIImageView *labelBackGroundView=[[UIImageView alloc] initWithFrame:textLabel.frame];
//標(biāo)簽背景圖片
labelBackGroundView.image=self.backgroundImageOfCanvas;
//*****label文字******
if (i<self.textArray.count) {
textLabel.text=self.textArray[i];
}else{
textLabel.text=@"----";
}
//label文字顏色(判斷文字顏色數(shù)組是否存有對應(yīng)的顏色,沒有則使用默認(rèn)顏色)
if (i<self.textColorArray.count) {
textLabel.textColor=self.textColorArray[i];
}else{
//默認(rèn)顏色
textLabel.textColor=[UIColor blackColor];
}
//******字體大小********
textLabel.font=[UIFont systemFontOfSize:self.fontOfSize];
//label標(biāo)簽tag值
textLabel.tag=LABEL_TAG_INIT + i + 100 * j;
//每創(chuàng)建一個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的話就會出現(xiàn)卡頓(與滑動等事件處于同一runLoop懦趋,系統(tǒng)會優(yōu)先響應(yīng)滑動)
小tips:定時器是可以暫停的
NSTimer 系統(tǒng)是沒有提供暫停的方法的晾虑,方法列表中只提供了-fire(啟動) 和 -invalidate(廢除)兩個方法,invalidate后是完全廢除不可再重啟
但是這里有個@property (copy) NSDate *fireDate的屬性仅叫,我們可以借助這個屬性來實(shí)現(xiàn)定時器的暫停和重啟
//立即啟動定時器
[timer setFireDate:[NSDate date]];
//暫停定時器
[timer setFireDate:[NSDate distantFuture]];
是不是有種很奇妙的感覺帜篇,這里利用定時器的啟動時間屬性巧妙的達(dá)到了暫停和重啟的目的
//************自動滾動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;
這里是定時器驅(qū)動scrollView滾動的方法
這里注意了如果要達(dá)到字幕連續(xù)滾動不斷幀的效果的話,timer調(diào)用需要非常頻繁(1秒調(diào)用10次以上)诫咱,此時再看看CPU使用率(@ο@)..瞬間飆升了20%左右笙隙,雖然還在能接受的范圍,但在這種小地方耗費(fèi)CPU顯然不劃算
解決方法:給個動畫過渡就好了嘛坎缭,UIView animateWithDuration輕松應(yīng)付竟痰,過渡很流暢,世界也瞬間安靜了掏呼。
后遺癥:用動畫過渡唯一的問題就是坏快,控制器跳轉(zhuǎn)后再回來的話,動畫會直接結(jié)束跳到尾幀憎夷,細(xì)心的用戶會發(fā)覺這奇怪的地方莽鸿,這就只有在性能和效果之間調(diào)和一下取最優(yōu)解了
//滾動時間間隔
#define SCROLL_TIME_INTERVAL 3
//每次滾動距離
#define SCROLL_DISTANCE 100
//自動滾動
- (void)autoScroll{
//滾動速度
CGFloat offSet=SCROLL_DISTANCE;
//若果字幕滾動到第二部分重復(fù)的部分則把偏移置0,設(shè)為第一部分,實(shí)現(xiàn)無限循環(huán)
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];
}
這一期就到這里了拾给,親們有什么意見和問題記得及時反饋哦祥得,喜歡的話點(diǎn)個關(guān)注給個贊(づ ̄3 ̄)づ╭?~
我們下期再會