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);
  }

}

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

(0)

相关推荐

  • Android 中RecycleView实现item的点击事件

    Android 中RecycleView实现item的点击事件 RecycleView现在已经越来越受到大家的重视,因为他既可以代替listView还可以代替GridView,但是RecycleView本身不不像ListView那样具有setOnItemClickListener,这个关于子item的点击,但是我们往往会用到RecycleView并且希望他的自孩子可以被点击,那么如何实现他的item的点击事件呢? 首先我们在RecyclerView.ViewHolder中的实现: public

  • Android RecycleView 实现左滑上下分层示例代码(自定义功能)

    由于项目原因,需要在很多地方需要左划删除,并在后期会在item中不定增加功能.网上很多左划删除的demo,但大多封装的不太彻底,所以就试着自己进行封装. 独立上下两层互补干扰,满足不同item的左划 底部功能项不定如(删除.收藏) 截图 独立Adapter的操作方式 思路: public RCommonSlideAdapter(Object object, List datas, int layoutId, Class clazz, SlideItemHolder handle) { 在onCr

  • Android RecycleView添加head配置封装的实例

    Android RecycleView添加head配置封装的实例 这个是把RecycleView的适配器给封装了,直接调用就可以了,还添加了可以添加head头部功能,很赞的,今天记下来,下次直接用 实例代码: package com.wwl.android; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.suppor

  • android中RecycleView添加下滑到底部的监听示例

    我们的日常开发中经常用到下拉刷新,而网上评价最好的开源下拉刷新组件当然还是android-Ultra-Pull-To-Refresh此组件可以给任何的控件添加下拉刷新功能.当然也包括recycleview了. 可惜android-Ultra-Pull-To-Refresh只是提供了下拉刷新的功能,但是对于列表类的组件,我们日常开发中更多的会用到其上拉加载或者滑到底部自动加载的功能,当然目前来看用户更喜欢滑到底部自动加载的功能.就比如今天说的recycleview我们只能自己给其添加滑到底部加载更

  • Android recycleView的应用和点击事件实例详解

    Android recycleView的应用和点击事件 效果图: 长按是删除: 下面代码: MainActivity 类 public class MainActivity extends AppCompatActivity { RecyclerView rv; List<String> mList = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.on

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

    本文实例为大家分享了RecycleView实现拖拽交换item位置的具体代码,供大家参考,具体内容如下 老规矩,先来一张效果图: 相比起ListView而言,RecycleView实现拖拽交换位置的效果要简单很多,因为通过SDK中的ItemTouchHelper工具类可以轻松的实现这种效果,并且一套代码支持所有布局方式;而ListView的话则需要通过生成View的缓存镜像设置到ImageView中,然后通过WindowManager来操作该ImageView,具体怎么实现这里就不展开讲解了.回

  • 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拖拽移位实现代码

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

  • Android仿qq消息拖拽效果

    本文实例为大家分享了Android仿qq消息拖拽效果展示的具体代码,供大家参考,具体内容如下 这是一个仿qq消息拖拽效果,View和拖拽实现了分离,TextView.Button.Imageview等都可以实现相应的拖拽效果:在触发的地方调用 MessageBubbleView.attach(findViewById(R.id.text_view), new MessageBubbleView.BubbleDisappearListener() { @Override public void d

  • Android实现悬浮可拖拽的Button

    本文实例为大家分享了Android实现悬浮可拖拽Button的具体代码,供大家参考,具体内容如下 1.简介 最近,因为项目需要,需要制作一个界面上可拖拽的按钮,网上也有多实例,看了下大部分都是示例不全或讲解不清晰,效果图也不明显,借此自己记录一番自己的实现方案,以备不时之需,同时也为广大学者可以直接通过拷贝方式完成项目所需. 2.效果图 在开始代码之前,首先看看效果图,如下: 3.核心代码实现 3.1 DraggingButton 实现 public class DraggingButton e

  • Vue实现移动端拖拽交换位置

    本文实例为大家分享了Vue实现移动端拖拽交换位置的具体代码,供大家参考,具体内容如下 <template> <div class="imageUploaderPage"> <ul ref='imgList' class="imgList"> <li ref='imgItem' class="imgCoverItem" v-for='(item, index) in filesResults' :key='

  • vue实现拖拽交换位置

    本文实例为大家分享了vue实现拖拽交换位置的具体代码,供大家参考,具体内容如下 <template>   <div class="root">     <transition-group tag="div" class="container">       <div         class="item"         :class="'item' + i"  

  • android的RecyclerView实现拖拽排序和侧滑删除示例

    在平时开发应用的时候,经常会遇到列表排序.滑动删除的需求.如果列表效果采用的是 ListView 的话,需要经过自定义 View 才能实现效果:但是如果采用的是 RecyclerView 的话,系统 API 就已经为我们提供了相应的功能. 接下来,我们就来看一下怎么用系统 API 来实现排序和删除的效果. 创建 ItemTouchHelper 创建一个 ItemTouchHelper 对象,然后其调用 attachToRecyclerView 方法: RecyclerView recyclerV

  • Android自定义View实现拖拽效果

    腾讯QQ有那种红点拖动效果,今天就来实现一个简单的自定义View拖动效果,再回到原处,并非完全仿QQ红点拖动. 先来看一下效果图 简单说一下实现步骤 1.创建一个类继承View 2.绘制出一个小球 3.重写onTouchEvent,来根据手指放下,移动,抬起,来控制小球 4.直接在布局中引用 先贴一张图看下View的坐标系 下面就贴一下代码,最后会给出源码 public class CustomView extends View { private int lastX; private int

  • JS实现图片拖拽交换效果

    JS实现图片拖拽交换效果,供大家参考,具体内容如下 听 WEB前端javascript企业实战班 公开课,用JS实现了图片拖拽交换的目的:感谢老师的讲解. 实现要点 鼠标点击onmousedown:获取鼠标在页面上可视区域的位置(clientX, clientY)和元素外边框距已定位父元素容器的位置(offsetLeft,offsetTop): 鼠标移动onmousemove: 获取鼠标在页面上可视区域的位置(clientX, clientY),并实时改变目标元素位置:进行碰撞检测,同时计算被碰

随机推荐