前言:昨天項(xiàng)目迭代增加一個(gè)功能臀防,對(duì)一個(gè)View在用戶看到的時(shí)候增加動(dòng)畫抢蚀,該View是在list作為footerView添加進(jìn)去的牛隅,需要判斷一個(gè)view對(duì)于用戶是否可見俘侠,也自己實(shí)踐了一下,總結(jié)總結(jié)薇搁。
網(wǎng)上查到的方法斋扰,有一個(gè)提到重寫view中“onWindowVisibilityChanged”的方法,來判斷是否可見啃洋,具體如下:
@Override
protected voidonWindowVisibilityChanged(intvisibility) {
super.onWindowVisibilityChanged(visibility);
if(visibility == View.VISIBLE){
//開始某些任務(wù)
if(!isCover()){
if(onViewVisibilityListener!=null){
onViewVisibilityListener.onVisible();
}
}
}else if(visibility ==INVISIBLE|| visibility ==GONE){
//停止某些任務(wù)
if(onViewVisibilityListener!=null){
onViewVisibilityListener.onInVisible();
}
}
}
ps:吐槽一下簡書這個(gè)編輯器對(duì)于代碼的規(guī)范化真的和屎一樣传货,當(dāng)然可能我自己沒學(xué)會(huì)掌握~
大寫的BUT,據(jù)我測試得出宏娄,該方法在第一次加載View的時(shí)候就觸發(fā)了(visibility== View.VISIBLE)问裕,然后隨著滑動(dòng)滑出滑入屏幕丫都沒有再次觸發(fā),網(wǎng)上查閱的對(duì)于該方法的解釋是:
onWindowVisibilityChanged(int) 當(dāng)窗口中包含的可見的view發(fā)生變化時(shí)觸發(fā)
經(jīng)過測試得出孵坚,該方法在在第一次加載繪制view時(shí)會(huì)被調(diào)用粮宛,然后在view被銷毀或者掛起時(shí)再被調(diào)用(如從當(dāng)前界面跳轉(zhuǎn)到其他activity時(shí)),詳細(xì)查閱以及跟蹤了其源代碼發(fā)現(xiàn)卖宠,調(diào)用該方法的地方主要在
網(wǎng)上查閱這兩個(gè)方法的解釋如下
所以此方法不能有效的監(jiān)聽改View是否在屏幕中可見巍杈,這個(gè)時(shí)候需要用到另一個(gè)方法
getGlobalVisibleRect(Rect r)
該方法是獲取視圖在屏幕坐標(biāo)中的可視區(qū)域,然后根據(jù)其返回的區(qū)域坐標(biāo)來進(jìn)行判斷是否被是否被遮住顯示不全逗堵。
cover= getGlobalVisibleRect(rect);
if(cover) {
if(rect.width() >= getMeasuredWidth() && rect.height() >= getMeasuredHeight()) {
//沒有被覆蓋
return!cover;
}
}
return true;
上述代碼只有在該View一半在屏幕中一半在屏幕外的時(shí)候才會(huì)返回true秉氧,其他都會(huì)返回false。
同時(shí)還有一個(gè)方法是:
getLocalVisibleRect(Rect r)
該方法是獲取視圖本身可見的坐標(biāo)區(qū)域蜒秤,坐標(biāo)以自己的左上角為原點(diǎn)(0汁咏,0)
該方法在該View一直在屏幕底部沒有顯示的時(shí)候亚斋,返回的下坐標(biāo)一直是view高度,如果從屏幕底部開始往上滑動(dòng)時(shí)攘滩,返回的下坐標(biāo)從0開始直到view的高度即View完全滑出屏幕帅刊。
所以機(jī)遇以上方法來進(jìn)行判斷View是否被遮擋,是否完全處于屏幕中漂问,結(jié)合View.getVisibility(),應(yīng)該可以滿足對(duì)于View是否可見的判斷赖瞒。(我使用的就是判斷是否被遮擋,如果被遮擋就出發(fā)動(dòng)畫蚤假,雖然有可能剛露個(gè)頭就觸發(fā)動(dòng)畫導(dǎo)致用戶還看不見栏饮,但是一般場景用戶不會(huì)一個(gè)位移一個(gè)位移的去滑動(dòng),如果遇到這樣變態(tài)的用戶磷仰,看不到動(dòng)畫效果也是他該E坻摇!T钇健)
題外話:
以上兩種方法都是主動(dòng)調(diào)用伺通,不是被動(dòng)調(diào)用,我們需要在view可見的時(shí)候觸發(fā)相應(yīng)的操作逢享,所以就需要在一個(gè)適當(dāng)?shù)臋C(jī)會(huì)主動(dòng)觸發(fā)去調(diào)用該方法判斷是否可見罐监,如果通過wihle(true)的方法,這又像小學(xué)生寫的代碼瞒爬,所以建議通過ListView的setOnScrollListener方法弓柱,在其回調(diào)
onScroll(AbsListView view, intfirstVisibleItem, intvisibleItemCount, inttotalItemCount)
方法時(shí)進(jìn)行判斷,因?yàn)楸敬涡枰獧z測的View是footerView疮鲫,就是放在最下面的View吆你,所以在onScroll中加了一個(gè)邏輯判斷
if(totalItemCount-visibleItemCount-firstVisibleItem>2){
return;
}
如果不是滑動(dòng)快到最下面的兩個(gè)View的時(shí)候(因?yàn)檫@個(gè)footerView是在倒數(shù)第二個(gè)View),就不進(jìn)行判斷俊犯,也算是減少一些無用的計(jì)算過程。
http://blog.sina.com.cn/s/blog_74c22b2101012urv.html