概述
通过上一篇文章相信大家都发现如果自定完全自定义一个RecyclerView条目的动画还是很复杂的,而且有许多要处理的地方,而且更重要的是,如果你不封装下,那么每个条目可以说是由很多重复的代码,不易维护,今天就带来一个动画框架,他实现了很常见的动画效果,而且还提供了扩展接口,最后我们演示在他的扩展接口上实现一个上一篇文章里面说的动画,就可以看出框架的强大性。
https://github.com/wasabeef/recyclerview-animators
添加依赖
compile ‘jp.wasabeef:recyclerview-animators:2.2.6’
设置动画
recyclerView.setItemAnimator(new SlideInLeftAnimator());
还可以更改插值器
SlideInUpAnimator animator = new SlideInUpAnimator(new OvershootInterpolator(1f));
recyclerView.setItemAnimator(animator);
通知Item
大家需要注意的是,如果要设置的动画有效果,就不能调用adapter的notifyDataSetChanged方法,而要调用这些方法:
notifyItemChanged(int)
notifyItemInserted(int)
notifyItemRemoved(int)
notifyItemRangeChanged(int, int)
notifyItemRangeInserted(int, int)
notifyItemRangeRemoved(int, int)
例如:
public void remove(int position) {
mDataSet.remove(position);
notifyItemRemoved(position);
}
public void add(String text, int position) {
mDataSet.add(position, text);
notifyItemInserted(position);
}
设置动画时间
recyclerView.getItemAnimator().setAddDuration(1000);
recyclerView.getItemAnimator().setRemoveDuration(1000);
recyclerView.getItemAnimator().setMoveDuration(1000);
recyclerView.getItemAnimator().setChangeDuration(1000);
在ViewHolder中覆盖动画
该框架提供一个强大的功能就是可以在ViewHolder覆盖默认的实现动画,只需要在ViewHolder中实现AnimateViewHolder接口,然后实现相应的方法,注意虽然这样实现了接口,但是还需要给REcyclerView设置动画,不然没效果。
class ViewHolder extends BaseRecyclerViewAdapter.ViewHolder
implements AnimateViewHolder
{
private final TextView tv;
public ViewHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(android.R.id.text1);
}
public void bindData(String data) {
tv.setText(data);
}
@Override
public void preAnimateRemoveImpl(RecyclerView.ViewHolder holder) {
}
@Override
public void animateRemoveImpl(RecyclerView.ViewHolder holder, ViewPropertyAnimatorListener listener) {
ViewCompat.animate(itemView)
.translationY(-itemView.getHeight() * 0.3f)
.alpha(0)
.setDuration(300)
.setListener(listener)
.start();
}
@Override
public void preAnimateAddImpl(RecyclerView.ViewHolder holder) {
ViewCompat.setTranslationY(itemView, -itemView.getHeight() * 0.3f);
ViewCompat.setAlpha(itemView, 0);
}
@Override
public void animateAddImpl(RecyclerView.ViewHolder holder, ViewPropertyAnimatorListener listener) {
ViewCompat.animate(itemView)
.translationY(0)
.alpha(1)
.setDuration(300)
.setListener(listener)
.start();
}
}
Adapter动画
所谓Adapter动画就是,滚动的时候Item的进入动画
SlideInLeftAnimationAdapter adapter = new SlideInLeftAnimationAdapter(useCustomAdapter);
// AlphaInAnimationAdapter adapter = new AlphaInAnimationAdapter(useCustomAdapter);
adapter.setFirstOnly(false); //每次都执行,默认false
// adapter.setDuration(1000);
rv.setAdapter(adapter);
效果如下:
还可以这样设置多个动画:
AlphaInAnimationAdapter adapter = new AlphaInAnimationAdapter(useCustomAdapter);
rv.setAdapter(new ScaleInAnimationAdapter(adapter));
扩展动画框架
这一部分我们讲解如何使用该动画框架实现上一节自定义添加,删除更新动画。
右边进入,左边移除Item动画
效果如下:
CustomSlideInRightAnimator
public class CustomSlideInRightAnimator extends BaseItemAnimator {
public CustomSlideInRightAnimator() {
}
public CustomSlideInRightAnimator(Interpolator interpolator) {
mInterpolator = interpolator;
}
@Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) {
ViewCompat.animate(holder.itemView)
.translationX(-holder.itemView.getRootView().getWidth())
.setDuration(getRemoveDuration())
.setInterpolator(mInterpolator)
.setListener(new DefaultRemoveVpaListener(holder))
.setStartDelay(getRemoveDelay(holder))
.start();
}
@Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) {
ViewCompat.setTranslationX(holder.itemView, holder.itemView.getRootView().getWidth());
}
@Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) {
ViewCompat.animate(holder.itemView)
.translationX(0)
.setDuration(getAddDuration())
.setInterpolator(mInterpolator)
.setListener(new DefaultAddVpaListener(holder))
.setStartDelay(getAddDelay(holder))
.start();
}
}
在animateAddImpl方法中实现添加条目动画。
右边进入Adapter动画
我们通过扩展adapter来实现一个从右边进入的Item动画,效果如下:
SlideInRightAnimationAdapter
public class SlideInRightAnimationAdapter extends AnimationAdapter {
public SlideInRightAnimationAdapter(
RecyclerView.Adapter adapter) {
super(adapter);
}
/**
- 从宽度变为0
- @param view
- @return
*/
@Override
protected Animator[] getAnimators(View view) {
return new Animator[]{
ObjectAnimator.ofFloat(view,“translationX”,view.getRootView().getWidth(),0)
};
}
}
使用的时候只需要用这个adapter包裹原来的adapter。
SlideInRightAnimationAdapter animationAdapter = new SlideInRightAnimationAdapter(
adapter);
animationAdapter.setFirstOnly(false);
rv.setAdapter(animationAdapter);