RecyclerView 列表项动画

上面是个视频,H.264。

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

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<E> 接口实现了一个 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;
        }
    }
}

/* ... */

嗯,好像没什么好说的。