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ù)
}
}