RecyclerView 列表项动画

原文:http://xingrz.me/2014/2014-11-02/recycler-view-item-animation.html 

re3543254.gif

正当我还在为毕业设计和两个课程大作业烦得焦头烂额之际…我又忍不住写了几行代码

RecyclerView 还带来了一个新特性:列表项动画(Item Animation)。同时自带了一个动画器是DefaultItemAnimator,大致上的效果就是挤开前后的列表项然后淡入(反之亦然)。

topicsView.setItemAnimator(new DefaultItemAnimator());

没错,如果你还是用 notifyDataSetChanged() 来通告数据集变更的话,你只会看到全部列表项一起淡出再淡入的效果。既然是列表项的动画,那么粒度当然要足够小:具体到某一项的增加、删除、移动、变更。于是 RecyclerView.Adapter 增加了下面几个方法:

  • notifyItemInserted(position) - 有一个新项插入到了 position 位置

  • notifyItemRangeInserted(position, count) - 在 position 位置插入了 count 个新项目

  • notifyItemRemoved(position)

  • notifyItemRangeRemoved(position, count)

  • notifyItemChanged(position)

  • notifyItemMoved(from, to)

  • ...

然后呢…考虑到 RecyclerView 目前就只有一个十分基本的 RecyclerView.Adapter,作为一个不折腾不舒服星人 (:зゝ∠),于是我自己仿照 ArrayAdapter 的做法用 List 接口实现了一个ArrayRecyclerAdapter,里面将这些方法都封装好了。

/* ... */
@Override
public void add(int location, E object) {
    synchronized (lock) {
        list.add(location, object);
        notifyItemInserted(location);
    }
}
@Override
public boolean add(E object) {
    synchronized (lock) {
        int lastIndex = list.size();
        if (list.add(object)) {
            notifyItemInserted(lastIndex);
            return true;
        } else {
            return false;
        }
    }
}
@Override
public boolean addAll(int location, Collection<? extends E> collection) {
    synchronized (lock) {
        if (list.addAll(location, collection)) {
            notifyItemRangeInserted(location, collection.size());
            return true;
        } else {
            return false;
        }
    }
}
@Override
public boolean addAll(Collection<? extends E> collection) {
    synchronized (lock) {
        int lastIndex = list.size();
        if (list.addAll(collection)) {
            notifyItemRangeInserted(lastIndex, collection.size());
            return true;
        } else {
            return false;
        }
    }
}
/* ... */

嗯,好像没什么好说的。