view 可見性 監(jiān)聽探究

view 可見性監(jiān)聽

今天產(chǎn)品有個需求,當(dāng)一個view任何又不可見->k可見時,上報這個view的特定信息。任何由不可見->可見,包括進(jìn)入一個頁面;從其他頁面返回到該頁面;在頁面內(nèi)view滑動出去又滑動回來可見時;屏幕熄滅->屏幕亮開此view顯示時。

某個view設(shè)定監(jiān)聽OnGlobalLayoutListener,作用范圍是頁面級的大布局,所以要馬上去掉

首先注意我們使用targetView.getViewTreeObserver().addOnGlobalLayoutListener(…)設(shè)置了OnGlobalLayoutListener時,是給targetView所在的整個view樹設(shè)置了監(jiān)聽(比如經(jīng)過測試我發(fā)現(xiàn):如果電影詳情頁頭部的一個view設(shè)置為targetView。那么我們滑動劇照(劇照view不在上面那個view的內(nèi)部),也會回調(diào)該監(jiān)聽。因為滑動劇照,會添加或去掉item view,引起整個布局layout的變動,所以會回調(diào)該監(jiān)聽)。所以我們要記住設(shè)置了OnGlobalLayoutListener之后,要在回調(diào)中馬上去掉這個監(jiān)聽。不然會回調(diào)很多遍,OnPreDrawListener也是如此,如果不馬上去掉,就會回調(diào)很多遍。

布局變化時,才會回調(diào)OnGlobalLayoutListener,所以滑動頁面不會引起回調(diào)OnGlobalLayoutListener

設(shè)置的OnGlobalLayoutListener是整個view樹中布局發(fā)生變化時才會回調(diào)。如果布局不變,那么不會回調(diào)(比如經(jīng)過測試發(fā)現(xiàn):設(shè)置了OnGlobalLayoutListener,滑動頁面,當(dāng)頁面從不可見變得可見時,并不會回調(diào)OnGlobalLayoutListener。因為頁面的layout布局并沒有變化,只是重新繪制了一遍)。

每次onresume時,view需要重新設(shè)置監(jiān)聽(不只是OnGlobalLayoutListener情況)

前面說了設(shè)置OnGlobalLayoutListener后需要在回調(diào)中去掉這次監(jiān)聽。所以我們需要每次onresume時,都要給view設(shè)置設(shè)置OnGlobalLayoutListener。如果只是在view生成的時候(比如oncreate()中)設(shè)置一次OnGlobalLayoutListener,這樣從其他頁面返回到該頁面、屏幕熄滅->屏幕亮?xí)r就不會回調(diào)了,因為這些時候不會走oncreate(),也就不會給view設(shè)置OnGlobalLayoutListener。為什么onresume()時會引起頁面layout的變化,從而OnGlobalLayoutListener觸發(fā)監(jiān)聽呢?因為onresume()時,會調(diào)用RootViewImpl#scheduleTraversals,從而走一遍測量、布局、繪制整個流程。
注意,不只是OnGlobalLayoutListener,OnPreDrawListener等監(jiān)聽都會存在這種情況,所以我們需要在每次走onresume時,設(shè)置監(jiān)聽。

listview中的itemview設(shè)置OnGlobalLayoutListener,任何時候view可見時都會回調(diào)OnGlobalLayoutListener

“需要每次onresume時,都要給view設(shè)置設(shè)置OnGlobalLayoutListener?!边@么做感覺很繁瑣。有沒有好的辦法呢?listview中的itemview如果可見性需要監(jiān)聽,那么還是很容易操作的。因為從其他頁面返回到該頁面、屏幕熄滅->屏幕亮?xí)r、滑動使某個view可見都會調(diào)用 bindItemData(ViewHolder holder, int dataIndex)方法。所以我們只要在bindItemData()方法中設(shè)置OnGlobalLayoutListener即可。別忘了在回調(diào)中取消哈)。

view不是listview中的itemview,滑動頁面時,view可見時怎么觸發(fā)回調(diào)。

重寫view的此方法,那么如果view在完全不可見時,會回調(diào)此方法;在view部分可見時,也會回調(diào)此方法。

@Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        if (visibility == View.VISIBLE){
            WLog.d("danxx" ,"可見");
            //開始某些任務(wù)
        }
        else if(visibility == INVISIBLE || visibility == GONE){
            WLog.d("danxx" ,"不可見");
            //停止某些任務(wù)
        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容