本文是通过分析github上的cypressious-AnimationListView控件来讲述如何给ListView的Item添加动画效果。先看看它的效果吧
图片来自cypressious的github项目示例图
这个AnimationListView是我使用AnimationListView来实现的一个例子,在AnimationListView.java中添加了一些注释,方便理解。在例子中还包含了SwipeLayout控件,所以最后的实现效果是这样的。
ok,下面开始分析实现原理。(本文主要分析ListView的动画实现,不会讲述swipeLayout——也就是横向滑动删除的效果。)
1.AdapterWrapper内部类
上面提供了代码的下载链接,最好还是下载一份对照着来看文章的分析。
AnimationListView.java文件一打开我们就会看到一个叫做AdapterWrapper的内部类,这个类是对用户的Adapter做一下包装,避免在动画执行的时候,用户调用adapter.notifyDataSetChanged()方法更新数据。
主要原理就是,启用一个AdapterWrapper类将用户的Adapter进行包装,而真正与ListView进行绑定的是新的AdapterWrapper对象。换句话说就是用户的Adapter是无法影响ListView的。当然,为了使我们的ListView可以根据用户的Adpater的来更新界面,在AdapterWrapper中创建了一个DataSetObserver对象,并将其注册给用户的Adapter,这样一来用户调用他的adapter.notifyDataSetChanged()时,我们的ListView可以更新到最新的界面。
这样我们只需要在DataSetObserver对象种做一些过滤处理,即可屏蔽用户Adapter的数据变更的影响了。
下面是这部分的具体代码
private static class AdapterWrapper extends BaseAdapter {
private final ListAdapter adapter;
private boolean mayNotify = true;
//实例化一个observer,用来观察原adapter的数据变化
private final DataSetObserver observer = new DataSetObserver() {
@Override
public void onChanged() {
if (mayNotify) { //动画执行时,会屏蔽原adapter的数据变化
notifyDataSetChanged();
}
}
@Override
public void onInvalidated() {
notifyDataSetInvalidated();
};
};
public AdapterWrapper(final ListAdapter adapter) {
this.adapter = adapter;
//将observer注册到原adapter中,以观察其数据变化
adapter.registerDataSetObserver(observer);
}
//设置是否屏蔽数据更新
public void setMayNotify(final boolean mayNotify) {
this.mayNotify = mayNotify;
}
@Override
public int getCount() {
return adapter.getCount();
}
@Override
public Object getItem(final int position) {
return adapter.getItem(position);
}
@Override
public long getItemId(final int position) {
return adapter.getItemId(position);
}