前言
上次有提到最近在封裝的一個控件卧秘,這個控件的名字還沒發(fā)現(xiàn)有統(tǒng)一的叫法,安卓里貌似是直接有這個控件的(TabHost)姆蘸,iOS中最普遍的應(yīng)該是稱之為“網(wǎng)易新聞的分頁頭視圖”墩莫,用過網(wǎng)易新聞的應(yīng)該不會陌生,簡書的分頁控制也是類似的效果逞敷。
網(wǎng)易新聞中狂秦,滑動頁面時,頭視圖的文字是有一個漸變的效果的(文字的顏色和字號)推捐,但這個漸變效果做的最好的裂问,個人感覺應(yīng)該是UC瀏覽器的新聞頁,UC頭視圖的文字漸變是一種填充效果,就像KTV的歌詞顯示那樣堪簿,可以做到單個文字顏色的漸變痊乾。
本著造輪子要徹底的心態(tài),也添加了類似的效果戴甩,關(guān)于這一效果的實現(xiàn)符喝,想到了兩種思路闪彼,一種是讓字體鏤空甜孤,改變背景色,另一種就是參考實現(xiàn)歌詞進度那樣的顯示效果畏腕。
先看一下Demo中關(guān)于將要介紹的幾種實現(xiàn)的整體效果:
Demo詳見GitHub:JXTMarkLabel
1.鏤空文字 - JXTHollowOutLabel
如果說上面的Demo效果還不夠直觀的話缴川,看這里的圖層關(guān)系:
鏤空文字效果的實現(xiàn)基于drawRect重繪,具體參考了兩篇帖子:
1.Drawing a path with subtracted text using Core Graphics
2.drawRect drawing 'transparent' text?
想了解原理的可以參考原文描馅,根據(jù)帖子中提供的代碼把夸,我這里稍作了簡化和封裝,也就是工程里的JXTHollowOutLabel類铭污。
效果實現(xiàn)的核心代碼如下:
- (void)drawSubtractedText:(NSString *)text inRect:(CGRect)rect inContext:(CGContextRef)context
{
//將當(dāng)前圖形狀態(tài)推入堆棧
CGContextSaveGState(context);
//設(shè)置混合色
CGContextSetBlendMode(context, kCGBlendModeDestinationOut);
//label上面添加label
UILabel *label = [[UILabel alloc] initWithFrame:rect];
label.font = _font;
label.text = text;
label.textAlignment = NSTextAlignmentCenter;
label.backgroundColor = _backgroundColor;
[label.layer drawInContext:context];
//把堆棧頂部的狀態(tài)彈出恋日,返回到之前的圖形狀態(tài)
CGContextRestoreGState(context);
}
該類的調(diào)用同系統(tǒng)的UILabel類似(該類是其子類),不過因為封裝的問題嘹狞,初始化僅支持initWithFrame
一種岂膳,也就是不支持xib。
再回到文章最開始的話題磅网,因為有了鏤空文字谈截,這個問題就很簡單了,只需要在這個label的底層添加一個可滑動的顏色塊涧偷,漸變效果也就有了簸喂,效果如下:
如果看得足夠仔細(xì),可以發(fā)現(xiàn)有幾個title之間存在很細(xì)的裂隙燎潮,那是因為我這里的標(biāo)題的label尺寸是根據(jù)文字長短動態(tài)計算的喻鳄,用了boundingRectWithSize
方法,實際發(fā)現(xiàn)确封,一旦title的內(nèi)容是中文和數(shù)字或字母混合的诽表,例如圖中的“b站”,就會產(chǎn)生計算誤差隅肥,雖然很小竿奏。。腥放。
這種鏤空字實現(xiàn)的缺憾之一就是沒能支持毛玻璃效果泛啸,如果能支持的話,那么背景的滑塊的顏色就可以透過來秃症,鏤空的質(zhì)感會更好候址,如果誰有帶毛玻璃的鏤空字效果的實現(xiàn)方法吕粹,一定要告訴我呀。
2.基于CoreAnimation的KTV歌詞視圖
這部分只是簡單提一下岗仑,因為我并不是用這種高大上的方法實現(xiàn)最前面的那個歌詞進度的效果的匹耕。
歌詞的進度顯示是個比較復(fù)雜的問題,除了刷新效率荠雕,還有就是刷新速度的動態(tài)變化的問題稳其,以及換行刷新,下面唱吧的那篇博文非常不錯炸卑,推薦下既鞠,還有一篇另外博文根據(jù)唱吧的思路提供了Demo可以學(xué)習(xí)。
3.歌詞進度顯示 - JXTProgressLabel
因為沒有像歌詞進度顯示那樣有那么多顧慮盖文,我這里使用了一種比較白癡的方法嘱蛋,這個方法原來是星級評價那里使用的,星級評價就是滿5星五续,根據(jù)數(shù)據(jù)動態(tài)展示幾點幾星的那個問題洒敏,有的人是直接幾星貼幾張圖,半星就是半顆星的圖疙驾,但實際上用兩層view再加一層控制的view凶伙,一共三層,疊加起來荆萤,就很容易實現(xiàn)這個效果:
上圖中:底層是白色字體的那個label镊靴,也就是
backgroundLabel
,中間層链韭,也就是現(xiàn)在標(biāo)示的藍(lán)色的透明view偏竟,是clipView
,最上層橙色文字的label敞峭,是foregroundLabel
踊谋。三者的層級關(guān)系如下:
[self addSubview:self.backgroundLabel];
[self.clipView addSubview:self.foregroundLabel];
[self addSubview:self.clipView];
foregroundLabel
是clipView
的子視圖,_clipView.clipsToBounds = YES
需要設(shè)置旋讹,此時控制clipView
的寬度殖蚕,也就控制了foregroundLabel
的文字顯示的進度(label的顯示寬度),backgroundLabel
和clipView
是并列關(guān)系沉迹,后者在前者圖層的上層睦疫,也就展現(xiàn)了背景l(fā)abel隨著中間層clipView
的動態(tài)寬度變化,從而動態(tài)渲染顏色的視覺假象鞭呕。星級控制也是同樣的原理蛤育。
JXTProgressLabel的使用也同系統(tǒng)的UIlabel類似,初始化也僅支持initWithFrame
一種,初始化時還需要設(shè)置前景和背景l(fā)abel的顏色:
_progressLabel.backgroundTextColor = [UIColor whiteColor];
_progressLabel.foregroundTextColor = [UIColor orangeColor];
控制顯示進度時瓦糕,支持兩種方法底洗,一種是直接控制clipView
的寬度,也就是_progressLabel.clipWidth
咕娄,但這種方式比較局限亥揖,推薦直接控制_progressLabel2.dispProgress
,dispProgress
是0-1之間的小數(shù)圣勒。
JXTProgressLabel除了可以作為類似的歌詞進度顯示费变,還可以做進度指示器,具體用法看具體需求了灾而。
4.歌詞進度顯示的升級 - JXTSlideClipLabel
還是回到最開始的問題胡控,如果直接使用之前提到的JXTProgressLabel扳剿,很明顯是不能直接滿足需求的旁趟,因為title的顏色是變過之后,又要變回的庇绽,所以锡搜,上面的JXTProgressLabel的clipView
的寬度應(yīng)該是限定的或者說應(yīng)該是隨著title長短動態(tài)改變的,而不是一直增大的瞧掺。
如果只是限制clipView
的寬度耕餐,位置水平移動,很明顯辟狈,其子視圖foregroundLabel
也會跟著移動肠缔,那么之前動態(tài)渲染的假象也就不復(fù)存在了,這里解決的方法也比較取巧:foregroundLabel
的frame同backgroundLabel
一樣哼转,但是其坐標(biāo)隨著固定寬度的clipView
的移動明未,反方向退行,三者之間的圖層關(guān)系還是不變的壹蔓。
具體的效果就是最開始的那個展示趟妥。
JXTSlideClipLabel在Demo中只是原理的封裝,沒有考慮具體情境而普適佣蓉,demo中是根據(jù)title數(shù)量披摄,動態(tài)創(chuàng)建了label,其實只使用一個label應(yīng)該也是可以的勇凭,只要保證三者的圖層關(guān)系就好疚膊。只是用一個label做foregroundLabel
或backgroundLabel
的話,標(biāo)題組應(yīng)該拼接起來成一個字符串虾标,具體沒有試寓盗,應(yīng)該是行得通的。
5.一種類似視差效果的視圖 - ParallaxView
雖然是這么叫的,但其實不是tableView的那種滑動的視察效果啦贞让,只是不知道該怎么稱呼周崭,記得是在哪個APP里見過這個效果的,只是一時想不起來了喳张,知道的朋友回我一下~
這個的實現(xiàn)原理和JXTSlideClipLabel一樣续镇,可以移動的view中貼了一張大圖,但限于clipView尺寸销部,只能顯示一部分摸航,這一部分根據(jù)移動的坐標(biāo),也動態(tài)“退行”舅桩,就成了這個效果酱虎,好像一塊“透視鏡”,比較有意思擂涛,那個圓形的本來是想試著做成一個放大鏡的读串,但是方法后的視圖的坐標(biāo)變換沒有處理好,暫時放棄了……
ParallaxView的代碼同樣只是演示撒妈,滑動視圖的邊界沒有限定恢暖,可以自行處理。
以上就是造輪子過程中遇到的幾個比較有意思的問題了狰右,總歸就是特種的label杰捂,使用情境可能比較局限,但是實現(xiàn)思路還是比較有意思的棋蚌。
參考文章:
1.iOS UILabel鏤空特效
2.Drawing a path with subtracted text using Core Graphics
3.drawRect drawing 'transparent' text?
4.RSMaskedLabel
5.iOS歌詞逐漸變色動畫
6.基于Core Animation的KTV歌詞視圖的平滑實現(xiàn)