目录

前言

创建ItemAnimator

处理重叠

总结

源码


前言

我们经常会遇到在一个list中删除一条数据,这时候一般会有一个飞出的动画效果,如下图:
在RecyclerView中可以通过setItemAnimator函数设置一个ItemAnimator,实现item的add、remove、change等动作的动效。下面我们就通过ItemAnimator来实现上面的效果。

创建ItemAnimator

首先创建一个类,继承至SimpleItemAnimator,如下:
class FlyAnimator extends SimpleItemAnimator{@Overridepublic boolean animateRemove(RecyclerView.ViewHolder holder) {return false;}@Overridepublic boolean animateAdd(RecyclerView.ViewHolder holder) {return false;}@Overridepublic boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {return false;}@Overridepublic boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop) {return false;}@Overridepublic void runPendingAnimations() {}@Overridepublic void endAnimation(RecyclerView.ViewHolder item) {}@Overridepublic void endAnimations() {}@Overridepublic boolean isRunning() {return false;}
}

SimpleItemAnimator是一个抽象类,需要实现几个函数。
因为我们要实现是一个remove的动作,需要在animateRemove中处理。这里我们参照DefaultItemAnimator的做法,首先需要两个list,然后在animateRemove将holder添加进list中,这里暂时不做处理,如下:

List<RecyclerView.ViewHolder> removeHolders = new ArrayList<>();
List<RecyclerView.ViewHolder> removeAnimators = new ArrayList<>();
@Override
public boolean animateRemove(RecyclerView.ViewHolder holder) {removeHolders.add(holder);return true;
}
至于另外一个list下面会用到。
既然我们在animateRemove函数中不做动效处理,那么应该在哪里处理?
答案是在runPedingAnimations中来处理,代码如下:
@Override
public void runPendingAnimations() {if(!removeHolders.isEmpty()) {for(RecyclerView.ViewHolder holder : removeHolders) {remove(holder);}removeHolders.clear();}
}
遍历removeHolders,依次执行remove,这个函数是自定义的,用于执行动画,代码如下:
private void remove(final RecyclerView.ViewHolder holder){removeAnimators.add(holder);TranslateAnimation animation = new TranslateAnimation(0, 1000, 0, 0);animation.setDuration(500);animation.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {dispatchRemoveStarting(holder);}@Overridepublic void onAnimationEnd(Animation animation) {removeAnimators.remove(holder);dispatchRemoveFinished(holder);if(!isRunning()){dispatchAnimationsFinished();}}@Overridepublic void onAnimationRepeat(Animation animation) {}});holder.itemView.startAnimation(animation);
}
可以看到就是对holder的itemview执行来一个移动动画。
这里使用removeAnimators来管理所有的remove动画,目前是判断所有的remove动画是否结束,这个判断在isRunning函数中,代码如下:
@Override
public boolean isRunning() {return !(removeHolders.isEmpty() && removeAnimators.isEmpty());
}
当两个list都为空的时候,所有动画都完成了,回到remove代码中这时候执行disPatchAnimationsFinished函数。
通过上面几步,实现了remove的动效,当我们执行的时候发现确实有了飞出的效果,但是下面的item却瞬间上移导致重叠。效果如下:

处理重叠

这是因为我们目前只定义了remove的效果,实际上不仅有飞出的动作还有一个上移的动作,所以还需要定义一下move的效果,同remove一样需要两个list,在animateMove函数中将holder添加至list中,如下:
List<RecyclerView.ViewHolder> moveHolders = new ArrayList<>();
List<RecyclerView.ViewHolder> moveAnimators = new ArrayList<>();
@Override
public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {holder.itemView.setTranslationY(fromY - toY);moveHolders.add(holder);return true;
}
注意在remove的一瞬间,下方的item实际上就已经上移了,所以在animateMove中设置item的translationY使其保持在未上移的位置。
然后同样在runPedingAnimations中处理,这时runPedingAnimations代码如下:
@Override
public void runPendingAnimations() {if(!removeHolders.isEmpty()) {for(RecyclerView.ViewHolder holder : removeHolders) {remove(holder);}removeHolders.clear();}if(!moveHolders.isEmpty()){for(RecyclerView.ViewHolder holder : moveHolders) {move(holder);}moveHolders.clear();}
}

这里move同样是自定义的一个函数,代码如下:

private void move(final MoveInfo moveInfo){moveAnimators.add(moveInfo);ObjectAnimator animator = ObjectAnimator.ofFloat(moveInfo.holder.itemView,"translationY", moveInfo.holder.itemView.getTranslationY(), 0);animator.setDuration(500);animator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationStart(android.animation.Animator animation) {dispatchMoveStarting(moveInfo.holder);}@Overridepublic void onAnimationEnd(android.animation.Animator animation) {dispatchMoveFinished(moveInfo.holder);moveAnimators.remove(moveInfo.holder);if(!isRunning()) dispatchAnimationsFinished();}});animator.start();
}
执行了一个属性动画,修改了item的translationY使其上移回原位置。同时注意修改isRunning函数,如下:
@Override
public boolean isRunning() {return !(removeHolders.isEmpty() && removeAnimators.isEmpty() && moveHolders.isEmpty() && moveAnimators.isEmpty());
}

这样就实现了一开始的飞出效果。

总结

总结一下,其实自定义ItemAnimator比较简单,虽然代码接近百行,但其实主要就是执行动画。需要注意的就是有些情况需要配合move的动作。
自定义ItemAnimator后,直接为RecyclerView设置即可:
list.setItemAnimator(new FlyAnimator());

设置后如果调用了adapter的notifyItemRemoved函数就会执行remove的动效。

源码

关注公众号:BennuCTech,发送“FlyAnimator”获取完整源码

自定义RecyclerView动画——实现remove飞出效果相关推荐

  1. HTMO DOM部分---小练习;列表之间移动、日期选择、好友选中、滑动效果、滚动条效果、飞入飞出效果。...

    一:列表之间数据移动 第一个列表里面有内容,第二个里面没有 实现功能: 点击左侧列表选中一项内容,点击按钮,复制到右侧 点击复制所有按钮,将左侧列表所有数据,复制到右侧 扩展功能:右侧列表实现去重复 ...

  2. Android搜索关键字飞入飞出效果(播放器的搜索界面)

    好多应用在搜索界面都有关键字飞入飞出的效果.我自己也实现了下.先上效果图: 实现该效果需要解决以下五点: 1.布局的选用. 2.确定动画区域,即布局的宽高. 3.对关键字坐标的随机分配. 4.对随机分 ...

  3. 安卓作业----慕课移动应用开发作业13之使用自定义RecyclerView.ItemDecoration实现列表悬浮顶部效果

    此博客通过RecyclerView.TextView等进行界面布局,使用自定义RecyclerView.Adapter.RecyclerViewAdapter.ViewHolder以及自定义Recyc ...

  4. 钱袋子动画(金币飞出,袋子内动态减少,钱袋子摇晃)

    简述 粗略构图,请发挥想象力哦,哈哈哈 触发点击事件时金币飞出,钱袋子摇晃 钱袋子里面的金币总量动态减少 思想 袋子内部动画就是上面波纹水平移动,金币总量垂直移动(transform:translat ...

  5. Android搜索关键字飞入飞出效果

    实现该效果需要解决以下五点: 1.布局的选用. 2.确定动画区域,即布局的宽高. 3.对关键字坐标的随机分配. 4.对随机分配的坐标进行向中心靠拢. 5.动画的实现. 本文内容归CSDN博客博主Sod ...

  6. Android实现搜索关键字飞入飞出效果

    效果图: 实现该效果需要解决以下五点: 1.布局的选用. 2.确定动画区域,即布局的宽高. 3.对关键字坐标的随机分配. 4.对随机分配的坐标进行向中心靠拢. 5.动画的实现. 本文内容归CSDN博客 ...

  7. 实现动画切换渐进渐出效果

    <body><button>显示</button><button>隐藏</button><button>切换</butto ...

  8. Android中自定义控件之飞入飞出布局及随机布局实现方式

    本文主要介绍Android中飞入飞出布局及随机布局的实现方式,具体的效果如下: 实现飞入飞出效果 FlyLayout.java /*** Created by MG_ZXC on 2018/3/24. ...

  9. 3dmax:3dmax经典案例详细步骤图文教程之飞出镜头的字母效果动画

    3dmax:3dmax经典案例详细步骤图文教程之飞出镜头的字母效果动画 目录 3dmax经典案例详细步骤图文教程之飞出镜头的字母效果动画 3dmax经典案例详细步骤图文教程之飞出镜头的字母效果动画

最新文章

  1. 这两者需要映射到相同的服务器,从而无法打开项目的解决方法:
  2. iOS 11开发教程(七)编写第一个iOS11代码Hello,World
  3. mysql 插入汉字异常: Incorrect string value: '\xE8\xB0\xA2\xE9\x9D\x99' for column 'uname' at row 1...
  4. 计算机科学课程体系核心内容,计算机科学教育的课程体系之研究
  5. 多线程介绍和多线程模块-lock-互斥锁
  6. 李宏毅机器学习课程---2、Regression - Case Study
  7. vmware安装centos问题
  8. 程序员被公司辞退12天,前领导要求回公司讲清楚代码,你们知道什么结果吗?
  9. python安装库的方法linalg_Python linalg.gmres方法代码示例
  10. echarts初次使用,自定义china-map省份默认颜色
  11. 系分 02 软件工程
  12. mysql分库分表中间件6_数据性能改善——分库分表中间件
  13. 【米勒拉宾模板】Palindromic Primes
  14. C2. Skyscrapers (hard version)
  15. 华为STUN类协议需要NAT ALG进行帮助吗
  16. 福建2021高考成绩查询是什么时间,2021年福建高考成绩排名及成绩公布时间什么时候出来...
  17. 鲸探发布点评:7月22日发售观德亭、全家福、龙凤呈祥熏数字藏品
  18. 集中趋势测度平均数之一(算术、调和、位置)
  19. 优秀工程师应该具备哪些素质_想成为一名合格的技术工程师需要具备哪些能力?...
  20. Oracle中新建数据表的两种方法

热门文章

  1. C# 数据结构 之 堆栈和队列
  2. 剑指offer试题(PHP篇一)
  3. 【Uva 10934】Dropping water balloons
  4. IntelliJ IDEA 建空包合并问题。
  5. const在c中的用法
  6. MetadataType的使用
  7. 【HDU2795】Billboard(线段树)
  8. The Tao to Excellent
  9. 【转】Hibernate数据过滤
  10. 设计模式学习-Composite(组合模式)