ItemTouchHelper:轻松实现滑动删除与拖拽重排
在 Android 开发中,为 RecyclerView 添加"滑动删除"和"拖拽重动"是提升用户体验的神技。以前这需要开发者手动计算坐标和处理动画,但自从有了 ItemTouchHelper,一切都变得优雅多了。本文将详细介绍如何使用 ItemTouchHelper 快速实现这些功能。
1、什么是 ItemTouchHelper?
ItemTouchHelper 是 AndroidX 提供的一个工具类,它封装了对触摸事件的处理,能够让你仅用几十行代码就实现复杂的列表交互。
- 自动处理触摸事件和手势识别
- 提供默认的动画效果
- 支持滑动删除和拖拽重排
- 高度可定制的回调机制
- 无需手动处理坐标计算和动画
2、实现滑动删除功能
2.1、基本实现
创建 ItemTouchHelper.Callback 实现:
public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
private final ItemTouchHelperAdapter adapter;
public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
this.adapter = adapter;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
return makeMovementFlags(dragFlags, swipeFlags);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
adapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
adapter.onItemDismiss(viewHolder.getAdapterPosition());
}
}
2.2、创建适配器接口
public interface ItemTouchHelperAdapter {
void onItemMove(int fromPosition, int toPosition);
void onItemDismiss(int position);
}
2.3、在适配器中实现接口
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>
implements ItemTouchHelperAdapter {
private List<String> items;
@Override
public void onItemMove(int fromPosition, int toPosition) {
Collections.swap(items, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
}
@Override
public void onItemDismiss(int position) {
items.remove(position);
notifyItemRemoved(position);
}
// 其他适配器方法...
}
2.4、配置 ItemTouchHelper
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(recyclerView);
3、自定义样式和动画
3.1、自定义滑动背景
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder, float dX, float dY,
int actionState, boolean isCurrentlyActive) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
View itemView = viewHolder.itemView;
// 创建渐变背景
Paint paint = new Paint();
paint.setColor(Color.RED);
if (dX > 0) {
// 向右滑动
c.drawRect(itemView.getLeft(), itemView.getTop(),
itemView.getLeft() + dX, itemView.getBottom(), paint);
} else {
// 向左滑动
c.drawRect(itemView.getRight() + dX, itemView.getTop(),
itemView.getRight(), itemView.getBottom(), paint);
}
// 绘制删除图标
Drawable icon = ContextCompat.getDrawable(context, R.drawable.ic_delete);
if (icon != null) {
int iconMargin = (itemView.getHeight() - icon.getIntrinsicHeight()) / 2;
int iconTop = itemView.getTop() + iconMargin;
int iconBottom = iconTop + icon.getIntrinsicHeight();
if (dX > 0) {
int iconLeft = itemView.getLeft() + iconMargin;
int iconRight = iconLeft + icon.getIntrinsicWidth();
icon.setBounds(iconLeft, iconTop, iconRight, iconBottom);
} else {
int iconRight = itemView.getRight() - iconMargin;
int iconLeft = iconRight - icon.getIntrinsicWidth();
icon.setBounds(iconLeft, iconTop, iconRight, iconBottom);
}
icon.draw(c);
}
}
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
3.2、自定义拖拽效果
@Override
public void onChildDrawOver(Canvas c, RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder, float dX, float dY,
int actionState, boolean isCurrentlyActive) {
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
// 拖拽时添加阴影效果
View itemView = viewHolder.itemView;
c.save();
c.clipRect(itemView.getLeft(), itemView.getTop(),
itemView.getRight(), itemView.getBottom());
// 绘制阴影
Paint shadowPaint = new Paint();
shadowPaint.setColor(Color.BLACK);
shadowPaint.setAlpha(64);
c.drawRect(itemView.getLeft(), itemView.getTop(),
itemView.getRight(), itemView.getBottom(), shadowPaint);
c.restore();
}
super.onChildDrawOver(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
4、高级功能实现
4.1、限制特定项的操作
@Override
public boolean canMove(RecyclerView.ViewHolder viewHolder) {
// 例如:第一个项不能移动
return viewHolder.getAdapterPosition() != 0;
}
@Override
public boolean canSwipe(RecyclerView.ViewHolder viewHolder) {
// 例如:最后一个项不能滑动删除
return viewHolder.getAdapterPosition() != items.size() - 1;
}
4.2、处理滑动阈值
@Override
public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) {
// 设置滑动阈值为50%
return 0.5f;
}
@Override
public float getMoveThreshold(RecyclerView.ViewHolder viewHolder) {
// 设置移动阈值
return 0.25f;
}
4.3、支持不同的滑动方向
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int position = viewHolder.getAdapterPosition();
// 根据位置设置不同的操作
if (position % 2 == 0) {
// 偶数位置支持拖拽和左右滑动
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
return makeMovementFlags(dragFlags, swipeFlags);
} else {
// 奇数位置只支持向左滑动
int swipeFlags = ItemTouchHelper.LEFT;
return makeMovementFlags(0, swipeFlags);
}
}
通过 ItemTouchHelper 可以轻松实现 RecyclerView 的滑动删除和拖拽重排功能,大大提升用户体验。