一、简述

RecyclerView默认就有item动画,例如在增加或删除item时,都会有一个条目间位移的动画,但本文要说的不是这个!!!本文的主角是v7包中的ItemTouchHelper,它跟RecyclerView结合后将会带来神奇的交互效果。示例如下:

效果还是比较酷炫的吧,上图中有四步操作:

  1. 长按item后拖动,与其他item交换位置
  2. 按住item右面的图标后拖动,与其他item交换位置
  3. 左滑item变透明并缩小,超出屏幕后,其他item补上
  4. 右滑item变透明并缩小,超出屏幕后,其他item补上

下面将一一实现出这些效果

二、初识ItemTouchHelper

1、创建ItemTouchHelper

// 创建ItemTouchHelper,并跟RecyclerView绑定
mItemTouchHelper = new ItemTouchHelper(mCallback);
mItemTouchHelper.attachToRecyclerView(mRv);复制代码

上面就是ItemTouchHelper在本例中出场的三行代码中的两行代码,但这并不能完成上面的效果,ItemTouchHelper只是一个中间人,它将ItemTouchHelper.Callback和RecyclerView连接起来,具体效果还需要由Callback实现。

2、自定义ItemTouchHelper.Callback

1)创建一个自己的Callback

继承ItemTouchHelper.Callback后必须实现如下三个方法。

public class MyItemTouchHelperCallback extends ItemTouchHelper.Callback {@Overridepublic int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {return 0;}@Overridepublic boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder targetViewHolder) {return false;}@Overridepublic void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {}
}复制代码

2)重写getMovementFlags()

getMovementFlags()是用来判断RecyclerView上的哪些方向操作交由ItemTouchHelper.Callback控制,详细介绍如下:

/*** 获取动作标识* 动作标识分:dragFlags和swipeFlags* dragFlags:列表滚动方向的动作标识(如竖直列表就是上和下,水平列表就是左和右)* wipeFlags:与列表滚动方向垂直的动作标识(如竖直列表就是左和右,水平列表就是上和下)*/
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {// 如果你不想上下拖动,可以将 dragFlags = 0int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;// 如果你不想左右滑动,可以将 swipeFlags = 0int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;//最终的动作标识(flags)必须要用makeMovementFlags()方法生成int flags = makeMovementFlags(dragFlags, swipeFlags);return flags;
}复制代码

上面我让item的上下左右都交由ItemTouchHelper.Callback控制,看下效果:

可以看到左右有效,但上下无效。仔细想想也是,本来就是竖直滚动列表,如果上下都直接交给ItemTouchHelper.Callback控制了,那RecyclerView的列表滚动功能该怎么办?所以,要触发上下拖动的交互效果,肯定有其他开启的方式。

3)开启长按item拖动效果

直接重写ItemTouchHelper.Callback的isLongPressDragEnabled()。

/*** 是否开启item长按拖拽功能*/
@Override
public boolean isLongPressDragEnabled() {return true;
}复制代码

默认返回是false,重写返回true。现在看下效果如何:

长按后可以拖动了,但是这样不太方便,接下来实现按住item右图标进行拖动的效果。

4)开启按住图标拖动效果

ItemTouchHelper的startDrag(viewHolder)方法可以手动开启拖动效果,上面的ItemTouchHelper实例创建在Activity中,而图标实例在Adapter中,为了降低耦合,这里先写一个接口:

public interface ItemDragListener {void onStartDrags(RecyclerView.ViewHolder viewHolder);
}复制代码

接口由Activity实现,在Adapter创建时传入

public class ItemTouchHelperActivity extends AppCompatActivity implements ItemDragListener {private ItemTouchHelper mItemTouchHelper;...private void setRecyclerView() {mAdapter = new ItemTouchHelperAdapter(mData, this);...}@Overridepublic void onStartDrags(RecyclerView.ViewHolder viewHolder) {mItemTouchHelper.startDrag(viewHolder);}
}复制代码

接口由Adapter的图标触摸时调用

public class ItemTouchHelperAdapter extends RecyclerView.Adapter<ItemTouchHelperAdapter.ItemTouchHelperViewHolder>  {private List<String> mData;private ItemDragListener mItemDragListener;public ItemTouchHelperAdapter(List<String> data, ItemDragListener itemDragListener) {mData = data;mItemDragListener = itemDragListener;}...@Overridepublic void onBindViewHolder(final ItemTouchHelperViewHolder viewHolder, int position) {...viewHolder.mIvDrag.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {mItemDragListener.onStartDrags(viewHolder);return false;}});}
}复制代码

这样在让图标在触摸时,间接的调用了mItemTouchHelper.startDrag(viewHolder),看下效果:

三、深入ItemTouchHelper

上面做到了item的上下拖动和左右滑动效果,但只是当前item的动画效果罢了,下面继续完成与其他item互动的效果吧。

1、上下拖动时与其他item进行位置交换

1)原理

其实ItemTouchHelper.Callback本身不具备将两个item互换位置的功能,但RecyclerView可以,我们可以在item拖动的时候把当前item与另一个item的数据位置交换,再调用RecyclerView的notifyItemMoved()方法刷新布局,同时,因为RecyclerView自带item动画,就可以完成上面的交互效果了。

2)实现

item拖动要在ItemTouchHelper.Callback中监听,而数据交换处理要在Adapter中进行,为了降低耦合,这里先写一个接口:

public interface ItemMoveListener {boolean onItemMove(int fromPosition, int toPosition);
}复制代码

接口由Adapter实现

public class ItemTouchHelperAdapter extends RecyclerView.Adapter<ItemTouchHelperAdapter.ItemTouchHelperViewHolder> implements ItemMoveListener{...@Overridepublic boolean onItemMove(int fromPosition, int toPosition) {//1、交换数据Collections.swap(mData, fromPosition, toPosition);//2、刷新notifyItemMoved(fromPosition, toPosition);return true;}
}复制代码

接口在创建ItemTouchHelper.Callback时传入,在onMove()中调用

public class MyItemTouchHelperCallback extends ItemTouchHelper.Callback {ItemMoveListener mItemMoveListener;public MyItemTouchHelperCallback(ItemMoveListener itemMoveListener) {mItemMoveListener = itemMoveListener;}...        /*** 当item拖拽移动时触发** @param recyclerView* @param viewHolder       当前被拖拽的item的viewHolder* @param targetViewHolder 当前被拖拽的item下方的另一个item的viewHolder* @return*/@Overridepublic boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder targetViewHolder) {return mItemMoveListener.onItemMove(viewHolder.getAdapterPosition(), targetViewHolder.getAdapterPosition());}
}复制代码

3)效果:

2、左右滑出屏幕时其他item补上

1)原理

相同的,只要在item滑出屏幕时,将对应的数据删掉,再调用RecyclerView的notifyItemRemoved()方法刷新布局即可。

2)实现

item滑动要在ItemTouchHelper.Callback中监听,而数据删除处理要在Adapter中进行,所以只需要加上面的接口中增加一个方法:

public interface ItemMoveListener {...boolean onItemRemove(int position);
}复制代码

接口由Adapter实现

public class ItemTouchHelperAdapter extends RecyclerView.Adapter<ItemTouchHelperAdapter.ItemTouchHelperViewHolder> implements ItemMoveListener{...@Overridepublic boolean onItemRemove(int position) {//1、删除数据mData.remove(position);//2、刷新notifyItemRemoved(position);return true;}
}复制代码

接口在ItemTouchHelper.Callback在onSwiped()中调用

/*** 当item侧滑出去时触发(竖直列表是侧滑,水平列表是竖滑)** @param viewHolder* @param direction  滑动的方向*/
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {mItemMoveListener.onItemRemove(viewHolder.getAdapterPosition());
}复制代码

3)效果:

现在大部分效果已经实现,接下来是细节处理。

3、交互时背景变化

1)原理

在item被拖拽或侧滑时修改背景色,当动作结束后将背景色恢复回来,而ItemTouchHelper.Callback中正好有对应这两个状态的方法,分别是:onSelectedChanged()、clearView()。

2)实现

/*** 当item被拖拽或侧滑时触发** @param viewHolder* @param actionState 当前item的状态*/
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {super.onSelectedChanged(viewHolder, actionState);//不管是拖拽或是侧滑,背景色都要变化if (actionState != ItemTouchHelper.ACTION_STATE_IDLE)viewHolder.itemView.setBackgroundColor(viewHolder.itemView.getContext().getResources().getColor(android.R.color.darker_gray));
}/*** 当item的交互动画结束时触发** @param recyclerView* @param viewHolder*/
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {super.clearView(recyclerView, viewHolder);viewHolder.itemView.setBackgroundColor(viewHolder.itemView.getContext().getResources().getColor(android.R.color.white));
}复制代码

3)效果

4、左右滑动时item渐变

1)分析及实现

在最开始的图中,当item被侧滑出去的过程中,可以看到item的透明度在渐渐变浅,高度在渐渐变小,其实就是让item执行了两种属性动画而已,在ItemTouchHelper.Callback中有一个方法可以拿到item被拖拽或滑动时的位移变化,那就是onChildDraw()方法,这样就很好办了,看如下代码实现:

@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {//这句代码就是item拖拽和滑动效果的实现,所以这句不能省略super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);//我们只需要在左右滑动时,将透明度和高度的值变小(1 --> 0)if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {float value = 1 - Math.abs(dX) / viewHolder.itemView.getWidth();viewHolder.itemView.setAlpha(value);viewHolder.itemView.setScaleY(value);}
}复制代码

2)效果(有瑕疵)

可以看到,item在滑动过程中渐渐透明并高度缩小了,但是,我明明是删除了两条,怎么结果列表中多出来两条空白的数据!这又是为什么呢?

3)修复

其实上图中并不是多出了两条空白数据,它们是正常的数据,只是看不到了,这是因为RecyclerView条目(itemView)覆用导致的,前面在onChildDraw()方法中对itemView设置了透明和缩小,而一个列表中固定只有几个itemView而已,当那两个透明缩小的itemView被再次使用时,之前设置的透明度和高度比例已经是0,所以就出现了这种情况,解决方法也很简单,只要在item被移除后,将itemView的透明度和高度比例设置回来即可,代码如下:

/*** 当item的交互动画结束时触发** @param recyclerView* @param viewHolder*/
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {super.clearView(recyclerView, viewHolder);...viewHolder.itemView.setAlpha(1);viewHolder.itemView.setScaleY(1);
}复制代码

4)效果(完美)

到这里,最开始的所有交互效果都已经实现了。

最后附上Demo链接

github.com/GitLqr/Mate…

RecyclerView 之使用 ItemTouchHelper 实现交互动画相关推荐

  1. RecyclerView之使用ItemTouchHelper实现交互动画

    一.简述 RecyclerView默认就有item动画,例如在增加或删除item时,都会有一个条目间位移的动画,但本文要说的不是这个!!!本文的主角是v7包中的ItemTouchHelper,它跟Re ...

  2. ItemTouchHelper 实现交互动画

    01.拖拽需要实现功能 需要实现拖拽的功能如下所示 长按item后拖动,与其他item交换位置 按住item右面的图标后拖动,与其他item交换位置 左滑item变透明并缩小,超出屏幕后,其他item ...

  3. Android ItemTouchHelper实现RecyclerView交互动画

    在上一次博客 Android RecyclerView使用详解,主要介绍了RecyclerView的基础使用,本篇文章将主要介绍通过ItemToucheHelper辅助类完成RecyclerView的 ...

  4. android:RecyclerView交互动画(上下拖动,左右滑动删除)

    效果 RecyclerView交互动画主要使用的是ItemTouchHelper这个类 创建MyItemTouchHelperCallback继承系统ItemTouchHelper.Callback ...

  5. Android开发之RecyclerView的交互动画(实现拖拽和删除)

    做RecyclerView做相关的动画效果的时候,用的最多的是v7包下的ItemTouchHelper类,这个类很强大,如有兴趣的童鞋可以自行翻看源码,接下来我带领大家实现RecyclerView相关 ...

  6. 【RecyclerView】 十五、使用 ItemTouchHelper 实现 RecyclerView 拖动排序 ( ItemTouchHelper 简介 )

    文章目录 一.ItemTouchHelper 简介 二.RecyclerView 相关资料 一.ItemTouchHelper 简介 官方文档 : https://developer.android. ...

  7. js svg语音波动动画_让动效更酷炫!4 个常见且常用的 SVG 交互动画方法

    本文介绍了 4 种常见的 SVG 交互动画方法,帮你了解 SVG 交互动画的原理和简单方法. 优秀的人机交互和舒适合理的动画,一直是 UX 设计师孜孜不倦追求的目标.但 UX 设计师每天都遇到能做出效 ...

  8. 交互 点击变色_这个95%的人都没用过的PPT功能,几分钟帮你做出发布会级的交互动画...

    我赌五毛,你一定没用过这个位于PPT插入选项卡的动作功能: 三顿就是用这个不起眼的小功能,制作了超多酷炫的交互动画.比如在做APP产品介绍时,点击左侧的按钮就能一键更换背景和产品图片: 甚至不用点击! ...

  9. [转]收集android上开源的酷炫的交互动画和视觉效果:Interactive-animation

    原文链接:http://www.open-open.com/lib/view/open1411443332703.html 描述:收集android上开源的酷炫的交互动画和视觉效果. 1.交互篇 2. ...

  10. Principle for Mac:让你五分钟即可制作出一个具有完整交互动画的原型

    Principle for Mac这款交互设计工具让你五分钟即可制作出一个具有完整交互动画的原型,并且可将交互动画生成视频或者 Gif 分享到 Dribbble.twitter 等社交平台. 无论您设 ...

最新文章

  1. rails采用MongoDB感觉相当不错!
  2. Jmeter4.0----CSV Data Set Config_对输入参数进行参数化(13)
  3. Spring.NET学习笔记——前言
  4. LeetCode 82 删除排序链表中的重复元素||-中等
  5. [转载]MVVM、MVVMLight、MVVMLight Toolkit之我见
  6. Oracle自定义类型
  7. Linux下的常用软件列表
  8. Mybatis mapper代理Dao开发
  9. DEVC++编译奇怪报错问题解决
  10. MAC OS Finder 中快速定位指定路径
  11. 【Android】科大讯飞——语音识别
  12. 管理信息系统需求调研分析指南
  13. 使用奇东锐腾PXE网克工具进行批量装机和系统恢复
  14. 基于C++实现(WinForm)家谱管理系统【100010033】
  15. 达人评测 小米笔记本pro14和联想yoga14s 选哪个好
  16. LaTeX中的中文处理方法
  17. 软件定义网络基础(SDN①)
  18. hexo yilia主题添加评论系统详细教程
  19. 价值500元的canvas图表是什么样的?
  20. 低码框架 json-script-rule 配置说明

热门文章

  1. python生产和消费模型_【Python】python 生产/消费模型
  2. oj交java代码_UvaOJ java输入代码
  3. 呼吁成立中国FreeType联盟
  4. LINUX SHELL中,变量如何加值
  5. SHELL判断文件是否包含某个字串
  6. NPAPI最简单的代码
  7. JDK多了一个shenandoah GC
  8. 头文件循环包含,导致找不到定义的类
  9. 买手机数据线特别要注意的地方
  10. python保留小数不四舍五入_Python常用知识小结