????????在AndroidTV中一般會把當(dāng)前擁有焦點的view放大顯示践美,而如果view之間的間隔較小放大后可能會造成壓邊情況钮呀,這時候常見的解決辦法就是讓擁有焦點的view掉用bringToFront()方法,但這種方法有一個問題就是如果該view的父布局是LinearLayout的話,獲取焦點的view會跑到LinearLayout的最后一個位置,也就是說LinearLayout中哪個子view獲取焦點哪個在LinearLayout的最后面
解決辦法:
?? ??? ?使用下面Github中的BringToFrontLinearLayout,直接替換掉布局中的LinearLayout即可癣漆,無需其他操作
Github地址:
原因分析:
?? ?? ? 我們先來看bringToFront()方法到的做了什么,為什么能夠解決壓邊問題剂买,
查看view源碼可以看到view中的bringToFront()其實是掉用父布局的bringChildToFront()方法
?? ??? ?而在viewGroup中bringChildToFront方法中的操作是
?? ??? ??? ?1惠爽,將這個子view從保存所有子view的數(shù)組中刪掉
?? ??? ?? ? 2,將view加入到子view數(shù)組到最后面
?? ??? ?? ? 3瞬哼,重新布局和重繪
?? ?? ?所以我們知道了bringToFront()方法其實就是把該view移到了父布局維護到子view數(shù)組的最后面婚肆,而viewGroup默認繪制子view流程是按其維護的數(shù)組依次繪制,最后位置的最后繪制自然不會被其他子view遮擋到
而linearLayout中掉用bringToFront()方法的子view會跑到linearLayout最后一個位置的原因坐慰,就是因為linearLayout的onLayout中會根據(jù)維護的子view數(shù)組順序進行布局较性,這一點在
bringToFront()方法的注釋中其實已經(jīng)說到了
if the parent container?uses an order-dependent layout scheme (e.g., LinearLayout)
解決辦法:
?? ??? ?前面已經(jīng)說了viewGroup的默認繪制子view流程是按子view數(shù)組順序進行的,那可不可以更改其繪制順序呢结胀?答案是可以赞咙!
?? ??? ?查看viewGroup源碼可以發(fā)現(xiàn)在dispatchDraw()方法中有上圖這樣一段代碼,我們可以看到在代碼中viwGroup繪制子view時會先掉用isChildrenDrawingOrderEnabled()方法得到一個boolean值糟港,然后把這個值傳入getAndVerifyPreorderedIndex()方法獲得下一個要繪制的子view的index
查看getAndVerifyPreorderedIndex()方法發(fā)現(xiàn)如果傳入的boolean值是true則會掉用getChildDrawingOrder()方法獲取index攀操,否則返回默認值
?? ?? ? 根據(jù)上面的分析,我們可以找到修改viewGroup繪制子view順序的方法:
1秸抚,讓isChildrenDrawingOrderEnabled()方法返回true(掉用setChildrenDrawingOrderEnabled(true)即可)
2速和,重寫getChildDrawingOrder()方法實現(xiàn)自定義繪制順序
這樣就可以做到既不會被其他元素壓邊又不會因為掉用bringToFront()方法而影響到到LinearLayout等線性布局的子view順序
Github地址: