RecyclerView 的拖动排序需要借助一下 ItemTouchHelper 这个类,ItemTouchHelper 类是 Google 提供的一个支持 RecyclerView 滑动和拖动的一个使用类,下面使用该类实现 RecyclerView 的滑动删除和拖动排序功能。首先大概介绍一下 ItemTouchHelper 的一个内部抽象类 Callback 类。

ItemTouchHelper.Callback

该类是ItemTouchHelper类中的一个静态抽象类,作用主要是将ItemTouchHelper于自己的应用联系在一起,让开发者通过ViewHolder控制每一个View的具体行为,接收用户的事件回调。该类里面有三个抽象方法:getMovementFlags、onMove、onSwiped。也是开发中经常要是用的。

getMovementFlags

该方法返回一个Flags表示Item的三种状态状态:idle(空闲)、 swiping(滑动)、dragging(拖动),根据RecyclerView不同的布局管理器,设置不同的滑动、拖动方向,一般使用makeMovementFlags(int dragFlags, int swipeFlags)方法返回,dragFlags表示拖动的方向,swipeFlags表示滑动的方向。

public abstract int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder);

onMove

当ItemTouchHelper拖动一个Item时该方法将会被回调,Item将从旧的位置移动到新的位置,如果不拖动这个方法将从来不会调用,返回true表示Item已经被移动到新的位置。

public abstract boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder, ViewHolder target);

onSwiped

当Item滑动的时候调用,如果不滑动该方法不会被调用,可通过direction做相应的判断执行某些操作。

public abstract void onSwiped(ViewHolder viewHolder, int direction);

此外经常使用的方法有 onSelectedChanged、clearView等方法。

onSelectedChanged

当item由静止状态变为滑动或拖动状态时调用此方法,可通过actionState判断Item在哪种状态下执行某些操作,重写该方法时必须调用其父类的该方法。

public void onSelectedChanged(ViewHolder viewHolder, int actionState) {
if (viewHolder != null) {
sUICallback.onSelected(viewHolder.itemView);
}
}

clearView

当与用户交互结束或相关动画完成之后被 调用该方法被调用。

public void clearView(RecyclerView recyclerView, ViewHolder viewHolder) {
sUICallback.clearView(viewHolder.itemView);
}

RecyclerView实现拖动排序

RecyclerView的拖动排序需要借助一个 android.support.v7.widget.helper.ItemTouchHelper 这个类来实现,拖动排序重点是在接口里面的 onMove(int fromPosition, int toPosition) 方法,其在GridAdapter中的具体实现参考如下:

@Override
public void onMove(int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(list, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(list, i, i - 1);
}
}
notifyItemMoved(fromPosition, toPosition);
}

RecyclerView实现侧滑删除

RecyclerView的拖动排序需要借助一个 android.support.v7.widget.helper.ItemTouchHelper 这个类来实现,侧滑删除重点是在接口中的 onSwiped(int position),其在GridAdapter中的具体实现参考如下:


@Override
public void onSwiped(int position) {
Log.i("drag","onSwiped");
list.remove(position);
notifyItemRemoved(position);
}

参考代码

ItemTouchHelper.Callback 的实现类

/**
* Created by jzman on 2017/5/17 0015.
*/
public class ItemTouchCallBack extends ItemTouchHelper.Callback {
private static final String TAG = "drag";
private OnItemTouchListener onItemTouchListener; public void setOnItemTouchListener(OnItemTouchListener onItemTouchListener) {
this.onItemTouchListener = onItemTouchListener;
} /**
* 根据 RecyclerView 不同的布局管理器,设置不同的滑动、拖动方向
* 该方法使用 makeMovementFlags(int dragFlags, int swipeFlags) 方法返回
* 参数: dragFlags:拖动的方向
* swipeFlags:滑动的方向
* @param recyclerView
* @param viewHolder
* @return
*/
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
Log.i(TAG,"getMovementFlags");
if (recyclerView.getLayoutManager() instanceof GridLayoutManager ||
recyclerView.getLayoutManager() instanceof StaggeredGridLayoutManager){
//此处不需要进行滑动操作,可设置为除4和8之外的整数,这里设为0
//不支持滑动
return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN |
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT, 0 );
}else {
//如果是LinearLayoutManager则只能向上向下滑动,
//此处第二个参数设置支持向右滑动
return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN , ItemTouchHelper.RIGHT );
}
} /**
* 当 ItemTouchHelper 拖动一个Item时该方法将会被回调,Item将从旧的位置移动到新的位置
* 如果不拖动这个方法将从来不会调用,返回true表示已经被移动到新的位置
* @param recyclerView
* @param viewHolder
* @param target
* @return
*/
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
Log.i(TAG,"onMove");
int fromPosition = viewHolder.getAdapterPosition();
int toPosition = target.getAdapterPosition();
onItemTouchListener.onMove(fromPosition,toPosition);
return true;
} /**
* 当Item被滑动的时候被调用
* 如果你不滑动这个方法将不会被调用
* @param viewHolder
* @param direction
*/
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
Log.i(TAG,"onSwiped");
//此处是侧滑删除的主要代码
int position = viewHolder.getAdapterPosition();
onItemTouchListener.onSwiped(position);
} /**
* 当Item被滑动、拖动的时候被调用
* @param viewHolder
* @param actionState
*/
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
Log.i(TAG,"onSelectedChanged");
//...
super.onSelectedChanged(viewHolder, actionState);
} /**
* 当与用户交互结束或相关动画完成之后被调用
* @param recyclerView
* @param viewHolder
*/
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
Log.i(TAG,"clearView");
//...
super.clearView(recyclerView, viewHolder);
} /**
* 移动交换数据的更新监听
*/
public interface OnItemTouchListener {
//拖动Item时调用
void onMove(int fromPosition, int toPosition);
//滑动Item时调用
void onSwiped(int position);
}
}

Adapter的实现

/**
* Created by jzman on 2017/05/17 0009.
* RecycleView的Adapter
*/
public class GridAdapter extends RecyclerView.Adapter<GridAdapter.DataViewHolder> implements View.OnClickListener,ItemTouchCallBack.OnItemTouchListener {
private Context context;
private List<SimpleTitleGrid> list; public GridAdapter(Context context, List<SimpleTitleGrid> list) {
this.context = context;
this.list = list;
} /**
* 创建ViewHolder
* @param parent
* @param viewType
* @return
*/
@Override
public DataViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//加载item布局文件(每一个)
View view = LayoutInflater.from(context).inflate(R.layout.item,null); //为View设置单击事件
view.setOnClickListener(this);
DataViewHolder viewHolder = new DataViewHolder(view); //使用代码设置宽高(xml布局设置无效时)
view.setLayoutParams(new RecyclerView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
return viewHolder;
} /**
* 绑定数据
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(DataViewHolder holder, int position) {
//设置每一个Item的高度
holder.textView.setText(list.get(position).getTitle());
} /**
* 选项总数
* @return
*/
@Override
public int getItemCount() {
return list.size();
} /**
* 单击事件
* @param v
*/
@Override
public void onClick(View v) {
if(onItemClickListener!=null){
int position = recyclerView.getChildAdapterPosition(v);
//程序执行到此,会执行该方法的具体实现
onItemClickListener.onItemClick(recyclerView,v,position,list.get(position));
}
} @Override
public void onMove(int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(list, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(list, i, i - 1);
}
}
notifyItemMoved(fromPosition, toPosition);
} @Override
public void onSwiped(int position) {
Log.i("drag","onSwiped");
list.remove(position);
notifyItemRemoved(position);
} /**
* RecycleView中针对ViewHolder来实现
*/
public static class DataViewHolder extends RecyclerView.ViewHolder {
TextView textView;
public DataViewHolder(View itemView) {
super(itemView);
textView = (TextView) itemView.findViewById(R.id.tv_grid);
}
}
private RecyclerView recyclerView;
private OnItemClickListener onItemClickListener;
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
/**
* 设计recycleView选项单击事件的回调接口(给外面使用)
* 参考ListView选项单击事件方法
*/
public interface OnItemClickListener{
//参数(父组件,点击的View,位置,这里可能是某个对象的id或对象/这里不需要)
void onItemClick(RecyclerView recyclerView, View view, int position, SimpleTitleGrid obj);
}
/**
* 将RecycleView附加到Adapter上
*/
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
this.recyclerView= recyclerView;
}
/**
* 将RecycleView从Adapter解除
*/
@Override
public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
super.onDetachedFromRecyclerView(recyclerView);
this.recyclerView = null;
}
}

MainActivity

/**
* Created by jzman on 2017/05/17 0029.
* RecycleView的Adapter
*/
public class MainActivity extends AppCompatActivity implements GridAdapter.OnItemClickListener{
private RecyclerView rv_user;
private GridAdapter adapter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
} private void initView() {
rv_user = (RecyclerView) findViewById(R.id.rv_user);
adapter = new GridAdapter(this, DataUtils.getUserGrids()); ItemTouchCallBack touchCallBack = new ItemTouchCallBack();
touchCallBack.setOnItemTouchListener(adapter);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(touchCallBack); rv_user.setLayoutManager(new GridLayoutManager(this,3));
// rv_user.setLayoutManager(new LinearLayoutManager(this));
rv_user.setAdapter(adapter);
itemTouchHelper.attachToRecyclerView(rv_user); adapter.setOnItemClickListener(this);
} @Override
public void onItemClick(RecyclerView recyclerView, View view, int position, SimpleTitleGrid obj) {
Toast.makeText(MainActivity.this, obj.getTitle(), Toast.LENGTH_SHORT).show();
}
}

显示效果

GridLayoutManager LinearLayoutManager

可关注微信公众号:jzman-blog 获取最新文章更新,一起交流学习!

RecyclerView实现拖动排序和滑动删除功能的更多相关文章

  1. ItemTouchHelper(实现RecyclerView上添加拖动排序与滑动删除的所有事情)

    简单介绍: ItemTouchHelper是一个强大的工具,它处理好了关于在RecyclerView上添加拖动排序与滑动删除的所有事情.它是RecyclerView.ItemDecoration的子类 ...

  2. RecyclerView拖拽排序和滑动删除实现

    效果图 如何实现 那么是如何实现的呢?主要就要使用到ItemTouchHelper ,ItemTouchHelper 一个帮助开发人员处理拖拽和滑动删除的实现类,它能够让你非常容易实现侧滑删除.拖拽的 ...

  3. Android学习之ItemTouchHelper实现RecylerView的拖拽以及滑动删除功能

    今天在群里见大神们提到控件的拖动以及滑动删除的效果实现,就在网上找了资料ItemTouchHelper学习,并实现其功能.不胜窃喜之至,忍不住跟大家分享一下,如今就对学习过程做下简介.帮助大家实现这样 ...

  4. 如何在RecyclerView上面实现"拖放"和"滑动删除"-1

    Android上面有许多的教程, 库和示例, 在RecyclerView上面实现"拖放"和"滑动删除"功能. 尽管有更新, 更好的方法可用, 但是大多数人依然使 ...

  5. RecyclerView借助ItemTouchHelper实现拖动和滑动删除功能

    RecyclerView是官方推荐代替ListView的空间,怎样实现RecyclerView列表元素的拖动呢? 官方提供了ItemTouchHelper类使用过程例如以下: 定义ItemTouchH ...

  6. 自定义listView添加滑动删除功能

    今天研究了一下android里面的手势,结合昨天学习的自定义View,做了一个自定义的listview,继承自listView,添加了条目的滑动手势操作,滑动后出现一个删除按钮,点击删除按钮,触发一个 ...

  7. 如何在RecyclerView上面实现"拖放"和"滑动删除"-2

    拖动手柄 在设计一个支持"拖放"的列表时, 通常提供一个在触摸时初始化拖拽的"拖动手柄". 因其可发现性和可用性而被Material Guidelines所推荐 ...

  8. Android滑动删除功能

    今天学习了新的功能那就是滑动删除数据.先看一下效果 我想这个效果大家都很熟悉吧.是不是在qq上看见过这个效果.俗话说好记性不如赖笔头,为了我的以后,为了跟我一样自学的小伙伴们,我把我的代码粘贴在下面. ...

  9. android 继承ListView实现滑动删除功能.

    在一些用户体验较好的应用上,可以经常遇见   在ListView中  向左或向右滑动便可删除那一项列表. 具体实现  则是继承ListView实现特定功能即可. (1). 新建 delete_butt ...

随机推荐

  1. 前端每日实战:146# 视频演示如何用纯 CSS 创作一个脉动 loader

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/wYvGwr 可交互视频 此视频是可 ...

  2. js判断PC端还是移动端的代码小坑

    我在写官网的时候做了pc和移动端两个,在通过网上查找了这样的代码,看着完全没问题,等放进去页面中后,PC端页面一直刷新,根本停不下来,找了类似js还是同样的问题.通过不断尝试后才发现,问题就是多了一行 ...

  3. seo搜索优化教程09 - seo搜索优化外链优化

    为了使大家更方便的了解及学习网络营销推广.seo搜索优化,星辉科技强势推出seo搜索优化教程.此为seo教程第九课 网络营销推广中有句行话,叫做"内容为王,外链为王",可见外链对于 ...

  4. scrapy-redis分布式爬取知乎问答,使用docker布置多台机器。

    先上结果: 问题: 答案: 可以看到现在答案文档有十万多,十万个为什么~hh 正文开始: 分布式爬虫应该是在多台服务器(A B C服务器)布置爬虫环境,让它们重复交叉爬取,这样的话需要用到状态管理器. ...

  5. 【07】openlayers 矢量图层

    创建地图: //创建地图 var map = new ol.Map({ //设置显示地图的视图 view: new ol.View({ center: [0, 0],//义地图显示中心于经度0度,纬度 ...

  6. R时间序列分析实例

    一.作业要求 自选时间序列完成时间序列的建模过程,要求序列的长度>=100. 报告要求以下几部分内容: 数据的描述:数据来源.期间.数据的定义.数据长度. 作时间序列图并进行简单评价. 进行时间 ...

  7. Windows通过VNC连接并显示Linux桌面(Ubuntu16.04)

    目录 Linux中安装VNC服务 Linux中安装桌面环境 Windows中安装VNC Viewer Linux中安装VNC服务 sudo apt-get update sudo apt-get in ...

  8. yarn安装Electron提示安装正常却实际没有安装的解决

    起因 使用Quasar框架开发Electron软件,配置好后发现electron没有正常安装,但是yarn却一本正经的胡说八道:不不不,electron已经在那里了.打开模块安装目录一看还真有elec ...

  9. javaScript 基础知识汇总 (十四)

    1.回调 什么是回调? 个人理解,让函数有序的执行. 示例: function loadScript(src,callback){ let script = document.createElemen ...

  10. 【vue生命周期】- 详解

    这篇文章通俗易懂,写的不错,本文转载至:https://www.cnblogs.com/happ0/p/8075562.html 详解Vue Lifecycle 先来看看vue官网对vue生命周期的介 ...