之前我们做点赞,用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完美解决。