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

 更新时间:2020年05月21日 11:45:36   作者:mChenys  
这篇文章主要为大家详细介绍了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);
 }

}

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

相关文章

  • Android 嵌套Fragment的使用实例代码

    Android 嵌套Fragment的使用实例代码

    本文主要介绍Android Fragment,在这里提供了实例代码跟效果图,希望能帮助有需要的小伙伴
    2016-07-07
  • Android Service自启动注意事项分析

    Android Service自启动注意事项分析

    这篇文章主要介绍了Android Service自启动注意事项,结合实例分析了Android Service自启动过程中属性设置的相关技巧,需要的朋友可以参考下
    2016-03-03
  • Android架构发展进化详解

    Android架构发展进化详解

    Android系统架构从上到下分为五层:应用层、应用框架层、系统运行库层、硬件抽象层、Linux内核层,Android架构也经历了多次演进,下面我们来详细了解一下
    2022-08-08
  • Android 在 res/layout 文件夹 下创建一个 子文件夹实例

    Android 在 res/layout 文件夹 下创建一个 子文件夹实例

    这篇文章主要介绍了Android 在 res/layout 文件夹 下创建一个 子文件夹实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-03-03
  • Android adb命令中pm工具的作用及用法说明

    Android adb命令中pm工具的作用及用法说明

    这篇文章主要介绍了Android adb命令中pm工具的作用及用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • 创建子线程对Android进行网络访问

    创建子线程对Android进行网络访问

    这篇文章介绍了Android中创建子线程进行网络访问的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考
    2021-11-11
  • Android中ListView的item点击没有反应的解决方法

    Android中ListView的item点击没有反应的解决方法

    这篇文章主要介绍了Android中ListView的item点击没有反应的相关资料,需要的朋友可以参考下
    2017-10-10
  • Kotlin Job启动流程源码层深入分析

    Kotlin Job启动流程源码层深入分析

    如果要我拿现实中的一事物与Kotlin协程中的Job做一个类比,那么我会把Job比作成海洋中的冰山。自由漂浮的冰山约有90%体积沉在海水表面下,因此看着浮在水面上的形状并猜不出水下的形状
    2022-11-11
  • android studio实现简单的计算器功能

    android studio实现简单的计算器功能

    这篇文章主要为大家详细介绍了android studio实现简单的计算器功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • Android 仿苹果底部弹出Dialog

    Android 仿苹果底部弹出Dialog

    这篇文章主要介绍了Android 仿苹果底部弹出Dialog的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-12-12

最新评论