前言:
RecyclerView如果实现拖拽功能,其实无非耗费太多时间,因为google已经帮我们封装好了,有相关接口暴露出来提供给我们使用,站在巨人肩膀上,我们试一试ItemTouchHelper
先看个简陋的效果图
step1:
现在布局文件加入RecyclerView,并在代码中初始化并绑定,代码简单不多说
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
this.mRecyView = (RecyclerView) findViewById(R.id.recyView);
mRecyView.setLayoutManager(new GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false));
mDatas = new ArrayList<>();
mAdapter = new MyAdapter(this, mDatas, mItemHelper, vb);
mRecyView.setAdapter(mAdapter);
给RecyclerView设置个模拟数据,便于我们测试看效果
for (int i = 0; i < 100; i++)
mDatas.add("加油小伙子! " + i);
mAdapter.notifyDataSetChanged();
添加适配器
/**
* Created by Administrator on 2018/3/14
*/
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private Context mContext;
private List<String> mDatas;
private ItemTouchHelper mItemHelper;
private Vibrator mVb;
public MyAdapter(Context mContext, List<String> mDatas, ItemTouchHelper itemHelper, Vibrator vb) {
this.mContext = mContext;
this.mDatas = mDatas;
this.mItemHelper = itemHelper;
this.mVb = vb;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new MyViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item, null, false));
}
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.tv.setText(mDatas.get(position));
holder.tv.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (position > 30) {
mItemHelper.startDrag(holder);
}
return false;
}
});
}
@Override
public int getItemCount() {
return mDatas.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
private View mView;
private TextView tv;
public MyViewHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(R.id.tv);
}
}
step2:
这是关键的地方,初始化ItemTouchHelper,并让RecyclerView绑定
ItemTouchHelper mItemHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
Log.e("hsjkkk", "getMovementFlags()");
if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN |
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
final int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags);
} else {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
final int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags);
}
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
Log.e("hsjkkk", "onMove()");
//得到当拖拽的viewHolder的Position
int fromPosition = viewHolder.getAdapterPosition();
//拿到当前拖拽到的item的viewHolder
int toPosition = target.getAdapterPosition();
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(mDatas, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(mDatas, i, i - 1);
}
}
mAdapter.notifyItemMoved(fromPosition, toPosition);
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
// Toast.makeText(MainActivity.this, "拖拽完成 方向" + direction, Toast.LENGTH_SHORT).show();
Log.e("hsjkkk", "拖拽完成 方向" + direction);
}
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
Log.e("hsjkkk", "onSelectedChanged()");
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE)
viewHolder.itemView.setBackgroundColor(Color.LTGRAY);
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
Log.e("hsjkkk", "clearView()");
viewHolder.itemView.setBackgroundColor(0);
}
//重写拖拽不可用
@Override
public boolean isLongPressDragEnabled() {
Log.e("hsjkkk", "isLongPressDragEnabled()");
return false;
}
});
//拖拽功能
mItemHelper.attachToRecyclerView(mRecyView);
实现ItemTouchHelper类
ItemTouchHelper mItemHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
Log.e("hsjkkk", "getMovementFlags()");
if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN |
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
final int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags);
} else {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
final int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags);
}
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
Log.e("hsjkkk", "onMove()");
//得到当拖拽的viewHolder的Position
int fromPosition = viewHolder.getAdapterPosition();
//拿到当前拖拽到的item的viewHolder
int toPosition = target.getAdapterPosition();
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(mDatas, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(mDatas, i, i - 1);
}
}
mAdapter.notifyItemMoved(fromPosition, toPosition);
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
// Toast.makeText(MainActivity.this, "拖拽完成 方向" + direction, Toast.LENGTH_SHORT).show();
Log.e("hsjkkk", "拖拽完成 方向" + direction);
}
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
Log.e("hsjkkk", "onSelectedChanged()");
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE)
viewHolder.itemView.setBackgroundColor(Color.LTGRAY);
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
Log.e("hsjkkk", "clearView()");
viewHolder.itemView.setBackgroundColor(0);
}
//重写拖拽不可用
@Override
public boolean isLongPressDragEnabled() {
Log.e("hsjkkk", "isLongPressDragEnabled()");
return false;
}
});
说一下这几个回调接口意思
getMovementFlags()是设置是否滑动时间,以及拖拽的方向,如果是列表布局的话则拖拽方向有DOWN和UP,如果是网格布局的话有DOWN和UP和LEFT和RIGHT4个方向
onMove()是在拖动的过程中不断回调的方法,在这里可以写上一些交换数据的逻辑
onSwiped()是拖动完成以后会回调的方法
onSelectedChanged()是在选中以后回调的方法
clearView()是拖放完成以后view被释放的方法
isLongPressDragEnabled()是重写是否允许item被拖拽的方法
demo中为了测试写的是positation>30的时候才允许拖拽