這小節(jié)會(huì)介紹如何減少透明區(qū)域?qū)π阅艿挠绊憽Mǔ?lái)說(shuō),對(duì)于不透明的View,顯示它只需要渲染一次即可,可是如果這個(gè)View設(shè)置了alpha值,會(huì)至少需要渲染兩次。原因是包含alpha的view需要事先知道混合View的下一層元素是什么,然后再結(jié)合上層的View進(jìn)行Blend混色處理。
在某些情況下,一個(gè)包含alpha的View有可能會(huì)觸發(fā)改View在HierarchyView上的父View都被額外重繪一次。下面我們看一個(gè)例子,下圖演示的ListView中的圖片與二級(jí)標(biāo)題都有設(shè)置透明度。
大多數(shù)情況下,屏幕上的元素都是由后向前進(jìn)行渲染的。在上面的圖示中,會(huì)先渲染背景圖(藍(lán),綠,紅),然后渲染人物頭像圖。如果后渲染的元素有設(shè)置alpha值,那么這個(gè)元素就會(huì)和屏幕上已經(jīng)渲染好的元素做blend處理。很多時(shí)候,我們會(huì)給整個(gè)View設(shè)置alpha的來(lái)達(dá)到fading的動(dòng)畫效果,如果我們圖示中的ListView做alpha逐漸減小的處理,我們可以看到ListView上的TextView等等組件會(huì)逐漸融合到背景色上。但是在這個(gè)過(guò)程中,我們無(wú)法觀察到它其實(shí)已經(jīng)觸發(fā)了額外的繪制任務(wù),我們的目標(biāo)是讓整個(gè)View逐漸透明,可是期間ListView在不停的做Blending的操作,這樣會(huì)導(dǎo)致不少性能問(wèn)題。
如何渲染才能夠得到我們想要的效果呢?我們可以先按照通常的方式把View上的元素按照從后到前的方式繪制出來(lái),但是不直接顯示到屏幕上,而是使用GPU預(yù)處理之后,再又GPU渲染到屏幕上,GPU可以對(duì)界面上的原始數(shù)據(jù)直接做旋轉(zhuǎn),設(shè)置透明度等等操作。使用GPU進(jìn)行渲染,雖然第一次操作相比起直接繪制到屏幕上更加耗時(shí),可是一旦原始紋理數(shù)據(jù)生成之后,接下去的操作就比較省時(shí)省力。
如何才能夠讓GPU來(lái)渲染某個(gè)View呢?我們可以通過(guò)setLayerType的方法來(lái)指定View應(yīng)該如何進(jìn)行渲染,從SDK 16開(kāi)始,我們還可以使用ViewPropertyAnimator.alpha().withLayer()來(lái)指定。如下圖所示:
另外一個(gè)例子是包含陰影區(qū)域的View,這種類型的View并不會(huì)出現(xiàn)我們前面提到的問(wèn)題,因?yàn)樗麄儾⒉淮嬖趯盈B的關(guān)系。
為了能夠讓渲染器知道這種情況,避免為這種View占用額外的GPU內(nèi)存空間,我們可以做下面的設(shè)置。
通過(guò)上面的設(shè)置以后,性能可以得到顯著的提升,如下圖所示: