之前我們做點贊,用listview做的話,就是在item實作點選後,寫一個scal動畫,不過現在都轉到recyclerview,那麼要做這種效果于是做了一個notifyitemchanged()的操作,功能都順利實作,美中不足的是目前item閃了一下,qa甚至為此提了bug,一開始以為是圖檔加載庫的問題,之後随着圖檔加載庫從imageloader換成picaso,又換成glide,這個bug一直如影随形。後來才發現“閃一下”原來是recyclerview的預設動畫,我的代碼裡有這樣一句<code>mrecyclerview.setitemanimator(new defaultitemanimator());</code>原來是這句代碼搞的鬼,于是注掉再跑,但并沒什麼卵用。于是又改成<code>mrecyclerview.setitemanimator(null);</code>仍然沒什麼卵用。看來加不加這句,recyclerview都預設執行了這個動畫,看來還有點小麻煩。
before.gif
先來了解下這個recyclerview的動畫吧。
recyclerview.itemanimator
itemanimator能夠幫助item實作獨立的動畫。
itemanimator觸發于以下三種事件:
某條資料被插入到資料集合中
從資料集合中移除某條資料
更改資料集合中的某條資料
在android中預設實作了一個defaultitemanimator
,我們可以通過以下代碼為item增加動畫效果:
<code>recyclerview.setitemanimator(new defaultitemanimator());</code>
在之前的版本中,當資料集合發生改變時,我們通過調用<code>notifydatasetchanged()</code>來重新整理清單,因為這樣做會觸發清單的重繪,是以并不會出現任何動畫效果,但現在我的需求是隻改變了目前一個item的狀态,是以需要調用一些以<code>notifyitem*()</code>作為字首的特殊方法,比如:
向指定位置插入item
<code>public final void notifyiteminserted(int position)</code>
移除指定位置item
<code>public final void notifyitemremoved(int position)</code>
更新指定位置item
<code>public final void notifyitemchanged(int position)</code>
但是現在的問題就是,調用notifyitem*()方法會觸發recyclerview的預設動畫,而這個動畫我并不想要,但是似乎并沒有合适的辦法來屏蔽這個動畫,qa甚至認為這是個bug,需要修複。與同行們交流了下,也有人遇到同樣的問題,解決辦法居然是調用notifydatasetchanged()方法來重新整理資料,這樣就不會有閃一下的動畫了。但是這樣不就失去使用recyclerview的優勢和意義了嗎?
最後我是通過重寫recyclerview的動畫來解決這一“bug”。
将defaultitemanimator類裡的代碼全部copy到自己寫的動畫類中,然後做一些修改。
首先找到<code>private void animatechangeimpl(final changeinfo changeinfo) {}</code>方法。
找到方法裡這兩句代碼:
1:<code>oldviewanim.alpha(0).setlistener(new vpalisteneradapter() { ... }</code>
2:<code>newviewanimation.translationx(0).translationy(0).setduration(getchangeduration()).alpha(1).setlistener(new vpalisteneradapter() { ... }</code>
替換成:
1:<code>oldviewanim.setlistener(new vpalisteneradapter() { ... }</code>
2<code>newviewanimation.translationx(0).translationy(0).setduration(getchangeduration()).setlistener(new vpalisteneradapter() { ... }</code>
也就是說分别去掉上述代碼中的<code>alpha(0)</code>和<code>alpha(1)</code>,然後儲存。這個時候基本就打工告成了。最後在自己的recyclerview中進行如下調用<code>mrecyclerview.setitemanimator(new noalphaitemanimator());</code>,再跑起來,bug完美解決。