Android使用RecycleView实现拖拽交换item位置

本文实例为大家分享了RecycleView实现拖拽交换item位置的具体代码,供大家参考,具体内容如下

老规矩,先来一张效果图:

相比起ListView而言,RecycleView实现拖拽交换位置的效果要简单很多,因为通过SDK中的ItemTouchHelper工具类可以轻松的实现这种效果,并且一套代码支持所有布局方式;而ListView的话则需要通过生成View的缓存镜像设置到ImageView中,然后通过WindowManager来操作该ImageView,具体怎么实现这里就不展开讲解了.回归到ItemTouchHelper话题上,这个工具类我们需要关心的方法只有一个,即:

public void attachToRecyclerView(@Nullable RecyclerView recyclerView) {}

通过名字也可以知道其作用就是和RecyclerView 建立关系.
而我们真正需要关心的地方就是ItemTouchHelper的内部类ItemTouchHelper.Callback,它是一个抽象类,需要我们去实现下面这几个关键的抽象方法以及重写几个非抽象的方法:

//决定拖拽/滑动的方向 public abstract int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder); //和位置交换有关,可用于实现drag功能 public abstract boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder, ViewHolder target); //和滑动有关,可用于实现swipe功能 public abstract void onSwiped(ViewHolder viewHolder, int direction); //是否长按启用拖拽功能,默认是true public boolean isLongPressDragEnabled() {return true;} //是否支持滑动,默认true public boolean isItemViewSwipeEnabled() {return true;} //和目标View的状态改变有关,例如drag,swipe,ide public void onSelectedChanged(ViewHolder viewHolder, int actionState) {} //和移除View的状态有关,通常用于清除在onSelectedChanged,onChildDraw中对View设置的动画 public void clearView(RecyclerView recyclerView, ViewHolder viewHolder) {}

当创建完ItemTouchHelper.Callback的实现类,我这里称之为SimpleItemTouchHelperCallback后,还需要将数据的变化以及View的状态通知到RecycleView的Adapter中,为了达到解耦的目的,通常可以通过定义接口来实现,在SimpleItemTouchHelperCallback的构造方法中传入该解耦接口的引用,并让RecycleView的Adapter实现该解耦的接口,这样就实现了这2个类的通信问题了.

来看看我定义的解耦接口:

/** * 定义RecycleView的Adapter和SimpleItemTouchHelperCallback直接交互的接口方法 * Created by mChenys on 2017/2/16. */ public interface ItemTouchHelperAdapter { //数据交换 void onItemMove(RecyclerView.ViewHolder source, RecyclerView.ViewHolder target); //数据删除 void onItemDissmiss(RecyclerView.ViewHolder source); //drag或者swipe选中 void onItemSelect(RecyclerView.ViewHolder source); //状态清除 void onItemClear(RecyclerView.ViewHolder source); }

完整的SimpleItemTouchHelperCallback代码如下:

/** * 处理RecycleView的选中,拖拽移动,拖拽删除的实现类 * Created by mChenys on 2017/2/16. */ public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback { private ItemTouchHelperAdapter mAdapter; public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) { mAdapter = adapter; } @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { //int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN; //允许上下的拖动 //int dragFlags =ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; //允许左右的拖动 //int swipeFlags = ItemTouchHelper.LEFT; //只允许从右向左侧滑 //int swipeFlags = ItemTouchHelper.DOWN; //只允许从上向下侧滑 //一般使用makeMovementFlags(int,int)或makeFlag(int, int)来构造我们的返回值 //makeMovementFlags(dragFlags, swipeFlags) int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; //允许上下左右的拖动 return makeMovementFlags(dragFlags, 0); } @Override public boolean isLongPressDragEnabled() { return true;//长按启用拖拽 } @Override public boolean isItemViewSwipeEnabled() { return false; //不启用拖拽删除 } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) { //通过接口传递拖拽交换数据的起始位置和目标位置的ViewHolder mAdapter.onItemMove(source, target); return true; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { //移动删除回调,如果不用可以不用理 // mAdapter.onItemDissmiss(viewHolder); } @Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { super.onSelectedChanged(viewHolder, actionState); if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) { //当滑动或者拖拽view的时候通过接口返回该ViewHolder mAdapter.onItemSelect(viewHolder); } } @Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder); if (!recyclerView.isComputingLayout()) { //当需要清除之前在onSelectedChanged或者onChildDraw,onChildDrawOver设置的状态或者动画时通过接口返回该ViewHolder mAdapter.onItemClear(viewHolder); } } }

RecycleView.Adapter实现类代码

/** * Created by mChenys on 2017/2/15. */ public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> implements ItemTouchHelperAdapter { ... @Override public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { ... } @Override public void onBindViewHolder(final MyAdapter.MyViewHolder holder, int position) { ... } @Override public int getItemCount() { //注意:这里最少有一个,因为有多了一个添加按钮 return null == mData ? 1 : mData.size() + 1; } @Override public void onItemMove(RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) { int fromPosition = source.getAdapterPosition(); int toPosition = target.getAdapterPosition(); if (fromPosition < mData.size() && toPosition < mData.size()) { //交换数据位置 Collections.swap(mData, fromPosition, toPosition); //刷新位置交换 notifyItemMoved(fromPosition, toPosition); } //移动过程中移除view的放大效果 onItemClear(source); } @Override public void onItemDissmiss(RecyclerView.ViewHolder source) { int position = source.getAdapterPosition(); mData.remove(position); //移除数据 notifyItemRemoved(position);//刷新数据移除 } @Override public void onItemSelect(RecyclerView.ViewHolder viewHolder) { //当拖拽选中时放大选中的view viewHolder.itemView.setScaleX(1.2f); viewHolder.itemView.setScaleY(1.2f); } @Override public void onItemClear(RecyclerView.ViewHolder viewHolder) { //拖拽结束后恢复view的状态 viewHolder.itemView.setScaleX(1.0f); viewHolder.itemView.setScaleY(1.0f); } public class MyViewHolder extends RecyclerView.ViewHolder { ... public MyViewHolder(View itemView) { super(itemView); ... } } }

MainActivity的使用方式

/** * Created by mChenys on 2017/2/16. */ public class MainActivity extends AppCompatActivity { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... mRecyclerView = (RecyclerView) findViewById(R.id.recycleView); //创建adapter MyAdapter myAdapter = new MyAdapter(this, mData); //设置默认的布局方式 mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); //设置adapter mRecyclerView.setAdapter(myAdapter); //创建SimpleItemTouchHelperCallback ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(myAdapter); //用Callback构造ItemtouchHelper ItemTouchHelper touchHelper = new ItemTouchHelper(callback); //调用ItemTouchHelper的attachToRecyclerView方法建立联系 touchHelper.attachToRecyclerView(mRecyclerView); } @Override public boolean onCreateOptionsMenu(Menu menu) { ... return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { ... return super.onOptionsItemSelected(item); } }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

时间: 2024-12-22 21:40:36

Android使用RecycleView实现拖拽交换item位置的相关文章

Android 可拖拽的GridView效果实现, 长按可拖拽和item实时交换

转帖请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/17718579),请尊重他人的辛勤劳动成果,谢谢! 在Android开发中,我们常常用到ListView和GridView,而有的时候系统的ListView,GridView并不能满足我们的需求,所以我们需要自己定义一个ListView或者GridView,我的上一篇文章中就是自定义的一个左右滑动删除item的例子,大家有兴趣的可以去看看 Android 使

Android中在GridView网格视图上实现item拖拽交换的方法_Android

GridView基础新建一个HelloGridView的工程 修改main.xml代码如下: <?xml version="1.0" encoding="utf-8"?> <GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gridview" android:layout_width=&qu

Android中在GridView网格视图上实现item拖拽交换的方法

GridView基础 新建一个HelloGridView的工程 修改main.xml代码如下: <?xml version="1.0" encoding="utf-8"?> <GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gridview" android:layout_width=&q

android ListView和GridView拖拽移位实现代码_Android

关于ListView拖拽移动位置,想必大家并不陌生,比较不错的软件都用到如此功能了.如:搜狐,网易,百度等,但是相比来说还是百度的用户体验较好,不偏心了,下面看几个示例:             首先说一下:拖拽ListView的item就不应该可以任意移动,只应该在ListView所在的范围内,而网易的你看看我都可以移动到状态栏了,虽然你做了处理,但是用户体验我个人感觉不好,在看看百度的,不仅控制了移动范围,更不错的百度的移动起来会时时的换位,看起来相当的形象,所以我认为这样相当的棒.说明一点

android ListView和GridView拖拽移位实现代码

关于ListView拖拽移动位置,想必大家并不陌生,比较不错的软件都用到如此功能了.如:搜狐,网易,百度等,但是相比来说还是百度的用户体验较好,不偏心了,下面看几个示例: 首先说一下:拖拽ListView的item就不应该可以任意移动,只应该在ListView所在的范围内,而网易的你看看我都可以移动到状态栏了,虽然你做了处理,但是用户体验我个人感觉不好,在看看百度的,不仅控制了移动范围,更不错的百度的移动起来会时时的换位,看起来相当的形象,所以我认为这样相当的棒.说明一点,我没有那么有才,我也是

ios-iphone,实现拖拽到同一位置

问题描述 iphone,实现拖拽到同一位置 嗨,应用中有拖拽选项,需要实现将对象拖拽到位置之后,在同一位置设置对象,但是我下面的代码实现不了,不知道怎么办?是在IOS6版本中的,谢谢大家们的帮助. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{CGPoint touchPoint = [[touches anyObject] locationInView:self.view];if (touchPoint.x >

Android ReboundScrollView仿IOS拖拽回弹效果

初衷: 其实github上有很多这种ScrollView的项目,但是不得不说功能太多太乱了,我就只是想要一个简单效果的ScrollView,另外监听下滑动距离而已,想想还是自己写了个. 这里先说下思路吧,如果不愿意看的朋友可以直接跳过这一步,看下面的代码: Android 原生的ScrollView是不支持拉出屏幕外,并且也没有回弹效果的,用户友好度却不不太好,不知道为什么不那么设计. 我想做的事情正如上面所述: 1.希望能拉出屏幕外 2.松手后希望控件回弹 我的思路是对ScrollView的子

用js控制组织结构图可以任意拖拽到指定位置

 用js控制生成了一个组织结构图并设置这个组织结构可以任意拖动到指定位置,具体代码如下 首先用js控制生成了一个组织结构图    再设置这个组织结构可以任意拖动到指定位置    页面代码如下 具体代码 实例 可以去我资源空间下载  代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional

android RecyclerView实现条目Item拖拽排序与滑动删除

效果演示 需求和技术分析 RecyclerView Item拖拽排序::长按RecyclerView的Item或者触摸Item的某个按钮. RecyclerView Item滑动删除:RecyclerView Item滑动删除:RecyclerView的Item滑动删除. 实现方案与技术 利用ItemTouchHelper绑定RecyclerView.ItemTouchHelper.Callback来实现UI更新,并且实现动态控制是否开启拖拽功能和滑动删除功能. 实现步骤 继承抽象类ItemTo