????????在AndroidTV中一般會(huì)把當(dāng)前擁有焦點(diǎn)的view放大顯示,而如果view之間的間隔較小放大后可能會(huì)造成壓邊情況,這時(shí)候常見(jiàn)的解決辦法就是讓擁有焦點(diǎn)的view掉用bringToFront()方法,但這種方法有一個(gè)問(wèn)題就是如果該view的父布局是LinearLayout的話,獲取焦點(diǎn)的view會(huì)跑到LinearLayout的最后一個(gè)位置,也就是說(shuō)LinearLayout中哪個(gè)子view獲取焦點(diǎn)哪個(gè)在LinearLayout的最后面
解決辦法:
?? ??? ?使用下面Github中的BringToFrontLinearLayout,直接替換掉布局中的LinearLayout即可,無(wú)需其他操作
Github地址:
原因分析:
?? ?? ? 我們先來(lái)看bringToFront()方法到的做了什么,為什么能夠解決壓邊問(wèn)題,

查看view源碼可以看到view中的bringToFront()其實(shí)是掉用父布局的bringChildToFront()方法

?? ??? ?而在viewGroup中bringChildToFront方法中的操作是
?? ??? ??? ?1,將這個(gè)子view從保存所有子view的數(shù)組中刪掉
?? ??? ?? ? 2,將view加入到子view數(shù)組到最后面
?? ??? ?? ? 3,重新布局和重繪
?? ?? ?所以我們知道了bringToFront()方法其實(shí)就是把該view移到了父布局維護(hù)到子view數(shù)組的最后面,而viewGroup默認(rèn)繪制子view流程是按其維護(hù)的數(shù)組依次繪制,最后位置的最后繪制自然不會(huì)被其他子view遮擋到
而linearLayout中掉用bringToFront()方法的子view會(huì)跑到linearLayout最后一個(gè)位置的原因,就是因?yàn)閘inearLayout的onLayout中會(huì)根據(jù)維護(hù)的子view數(shù)組順序進(jìn)行布局,這一點(diǎn)在
bringToFront()方法的注釋中其實(shí)已經(jīng)說(shuō)到了
if the parent container?uses an order-dependent layout scheme (e.g., LinearLayout)
解決辦法:
?? ??? ?前面已經(jīng)說(shuō)了viewGroup的默認(rèn)繪制子view流程是按子view數(shù)組順序進(jìn)行的,那可不可以更改其繪制順序呢?答案是可以!

?? ??? ?查看viewGroup源碼可以發(fā)現(xiàn)在dispatchDraw()方法中有上圖這樣一段代碼,我們可以看到在代碼中viwGroup繪制子view時(shí)會(huì)先掉用isChildrenDrawingOrderEnabled()方法得到一個(gè)boolean值,然后把這個(gè)值傳入getAndVerifyPreorderedIndex()方法獲得下一個(gè)要繪制的子view的index

查看getAndVerifyPreorderedIndex()方法發(fā)現(xiàn)如果傳入的boolean值是true則會(huì)掉用getChildDrawingOrder()方法獲取index,否則返回默認(rèn)值
?? ?? ? 根據(jù)上面的分析,我們可以找到修改viewGroup繪制子view順序的方法:
1,讓isChildrenDrawingOrderEnabled()方法返回true(掉用setChildrenDrawingOrderEnabled(true)即可)
2,重寫(xiě)getChildDrawingOrder()方法實(shí)現(xiàn)自定義繪制順序
這樣就可以做到既不會(huì)被其他元素壓邊又不會(huì)因?yàn)榈粲胋ringToFront()方法而影響到到LinearLayout等線性布局的子view順序
Github地址: