temTouchHelper,可以很好的处理RecyclerView的item的滑动拖拽功能。
ItemTouchHelper是android.support.v7.widget.helper包中的一个类,但现在android官方文档搜索,你会发现有两个ItemTouchHelper,其中是这个包下,另一个是androidx.recyclerview.widget包下的,根据官网说法androidx是新推出的软件包结构,一些support包都向androidx下迁移。不过现在support现在还是可以用的,Google给开发者一定的迁移时间。
ItemTouchHelper的构造方法需要传入ItemTouchHelper.Callback来实现对拖拽的监听。
现在就来看看ItemTouchHelper.Callback的一些方法
ItemTouchHelper.Callback是一个抽象类或者匿名内部类实现它,都必须实现它下面几个抽象方法
//拖拽的标志
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
//移动的监听
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)
// 滑动的回调
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction)
简单的使用
长按可以进行拖拽交换位置,左右可以滑动删除
适配器代码
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> {
private ArrayList<String> lists;
public RecyclerViewAdapter(ArrayList<String> lists) {
this.lists = lists;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycle, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
holder.tv.setText(lists.get(position));
}
@Override
public int getItemCount() {
return lists.size();
}
/** 删除数据
* @param position
*/
public final void delData(int position) {
lists.remove(position);
notifyItemRemoved(position);
}
/** 移动进行数据交换
* @param fromPosition
* @param toPosition
*/
public final void move(int fromPosition, int toPosition) {
Collections.swap(lists, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
}
class MyViewHolder extends RecyclerView.ViewHolder {
AppCompatTextView tv;
private MyViewHolder(View itemView) {
super(itemView);
tv = itemView.findViewById(R.id.tv);
}
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private RecyclerViewAdapter recyclerViewAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recycler_view);
//模拟数据
ArrayList<String> lists = new ArrayList<>();
for (int i = 0; i < 10; i++) {
lists.add("item" + i);
}
recyclerViewAdapter = new RecyclerViewAdapter(lists);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(recyclerViewAdapter);
final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelper.Callback() {
/**
*
* @param recyclerView 关联的recyclerView
* @param viewHolder 操作的viewHolder对象
* @return 返回运动方向标志的组合,通过makeMovementFlags(dragFlags, swipeFlags)进行组合
*/
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//拖拽的方法标记
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
//滑动方向标记
int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
//通过makeMovementFlags方法将将方向标记进行组合,并将复合的值返回
return makeMovementFlags(dragFlags, swipeFlags);
}
/**
* @param recyclerView 关联的recyclerView
* @param viewHolder 要移动的viewHolder对象
* @param target 移动到的目标ViewHolder对象
* @return 返回true 才会执行ItemTouchHelper.Callback的onMoved方法,
*/
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
recyclerViewAdapter.move(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
/**
* @param viewHolder 滑动的viewHolder对象
* @param direction 移动的方向标识
*/
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
recyclerViewAdapter.delData(viewHolder.getAdapterPosition());
}
});
//关联RecyclerView
itemTouchHelper.attachToRecyclerView(recyclerView);
}
}
如果想操作item条目是想让条目高亮怎么办,如下面效果?
想实现这种效果就要重写ItemTouchHelper.Callback的两个方法
// 拖拽或者滑动时调用
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState)
//拖拽或者滑动结束后调用
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
具体实现
/**
* @param viewHolder 操作的ViewHolder对象
* @param actionState 当前的状态, ItemTouchHelper.ACTION_STATE_IDLE,闲置状态
* ItemTouchHelper.ACTION_STATE_SWIPE,开始滑动状态
* ItemTouchHelper.ACTION_STATE_DRAG,开始拖拽
*/
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
//如果不是现实状态
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
//设置背景颜色为蓝色
viewHolder.itemView.setBackgroundColor(viewHolder.itemView.getResources().getColor(android.R.color.holo_blue_light));
if (viewHolder instanceof RecyclerViewAdapter.MyViewHolder) {
RecyclerViewAdapter.MyViewHolder myViewHolder = (RecyclerViewAdapter.MyViewHolder) viewHolder;
//设置字体为白色
myViewHolder.tv.setTextColor(Color.WHITE);
}
}
super.onSelectedChanged(viewHolder, actionState);
}
/** 还原状态
* @param recyclerView
* @param viewHolder
*/
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
viewHolder.itemView.setBackgroundColor(Color.TRANSPARENT);
if (viewHolder instanceof RecyclerViewAdapter.MyViewHolder) {
RecyclerViewAdapter.MyViewHolder myViewHolder = (RecyclerViewAdapter.MyViewHolder) viewHolder;
myViewHolder.tv.setTextColor(Color.BLACK);
}
super.clearView(recyclerView, viewHolder);
}
上面代码可以看到在onSelectedChanged
中获得viewHolder对象,就可以对RecyclerView的条目进行一些操作,如上面背景颜色的改变,还可以设置条目的一些动画效果,当然一定要记得再clearView
还原条目的改变,否则回出现一些奇怪的情况,因为RecyclerView条目是View是复用的。
非长按拖拽效果
ItemTouchHelper 默认是长按触发拖拽,当然我们可以设置非长按拖拽效果,例如按住一个图片进行拖拽
实现方法
1 在适配器重写这个图片的OnTouchListener
方法
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
holder.tv.setText(lists.get(position));
//设置holder.img 的OnTouchListener方法
holder.img.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
//dragListener 是适配器内部接口
if (dragListener != null) {
dragListener.onDrag(holder);
}
}
return false;
}
});
}
public interface DragListener {
/**
* 使用接口回调的方式将ViewHolder返回
* @param holder
*/
void onDrag(MyViewHolder holder);
}
private DragListener dragListener;
public void setDragListener(DragListener dragListener) {
this.dragListener = dragListener;
}
2 在MainActivity中设置接口回调
recyclerViewAdapter.setDragListener(new RecyclerViewAdapter.DragListener() {
@Override
public void onDrag(RecyclerViewAdapter.MyViewHolder holder) {
// 手动的条用ItemTouchHelper的开始拖拽方法
itemTouchHelper.startDrag(holder);
}
});