Android RecyclerView实现左右滑动删除/归档(分色显示)的方法
实现RecyclerView左右滑不同效果(左删右归档)的方案
嘿,我之前也折腾过一模一样的需求!用你现有的ItemTouchHelper完全能搞定双方向滑动的不同视觉和功能效果,不用换别的框架,咱们直接改代码就行,步骤很清晰:
1. 开启双向滑动权限
首先修改ItemTouchHelper.SimpleCallback的构造参数,把滑动方向从单一的LEFT改成LEFT | RIGHT,这样就允许左右两个方向的滑动了:
ItemTouchHelper.SimpleCallback swipeCallback = new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { // 后续方法重写... };
(第一个参数是拖拽方向,不需要的话传0就行)
2. 在onSwiped中区分方向处理业务逻辑
滑动结束后,根据不同的方向执行删除或归档操作:
@Override public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { int position = viewHolder.getAdapterPosition(); if (direction == ItemTouchHelper.LEFT) { // 左滑:执行删除逻辑 yourAdapter.removeItem(position); } else if (direction == ItemTouchHelper.RIGHT) { // 右滑:执行归档逻辑 yourAdapter.archiveItem(position); } }
3. 核心:在onChildDraw中绘制不同方向的背景和图标
这一步是实现视觉差异化的关键,我们要根据滑动的偏移量dX判断方向(dX>0是右滑,dX<0是左滑),然后分别绘制对应的背景色和图标:
首先提前初始化好需要的画笔和图标:
// 初始化背景画笔 Paint deleteBgPaint = new Paint(); deleteBgPaint.setColor(ContextCompat.getColor(context, R.color.swipe_delete_red)); deleteBgPaint.setStyle(Paint.Style.FILL); Paint archiveBgPaint = new Paint(); archiveBgPaint.setColor(ContextCompat.getColor(context, R.color.swipe_archive_blue)); archiveBgPaint.setStyle(Paint.Style.FILL); // 初始化图标 Drawable deleteIcon = ContextCompat.getDrawable(context, R.drawable.ic_delete_outline); Drawable archiveIcon = ContextCompat.getDrawable(context, R.drawable.ic_archive_outline);
然后重写onChildDraw方法:
@Override public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { View itemView = viewHolder.itemView; int iconSize = deleteIcon.getIntrinsicHeight(); int iconMargin = (itemView.getHeight() - iconSize) / 2; // 让图标垂直居中 if (dX > 0) { // 右滑:绘制归档背景和图标 // 绘制背景矩形:从item左边缘到滑动偏移位置 c.drawRect( itemView.getLeft(), itemView.getTop(), itemView.getLeft() + dX, itemView.getBottom(), archiveBgPaint ); // 设置图标位置:左边缘+边距,垂直居中 archiveIcon.setBounds( itemView.getLeft() + iconMargin, itemView.getTop() + iconMargin, itemView.getLeft() + iconMargin + iconSize, itemView.getBottom() - iconMargin ); archiveIcon.draw(c); } else if (dX < 0) { // 左滑:绘制删除背景和图标 // 绘制背景矩形:从滑动偏移位置到item右边缘 c.drawRect( itemView.getRight() + dX, itemView.getTop(), itemView.getRight(), itemView.getBottom(), deleteBgPaint ); // 设置图标位置:右边缘-边距-图标宽度,垂直居中 deleteIcon.setBounds( itemView.getRight() - iconMargin - iconSize, itemView.getTop() + iconMargin, itemView.getRight() - iconMargin, itemView.getBottom() - iconMargin ); deleteIcon.draw(c); } // 必须调用父类方法,保证item的滑动动画正常执行 super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); }
额外注意事项
- 如果你之前用了前景+背景的XML布局,现在可以去掉背景布局了,因为我们直接通过Canvas绘制背景,更灵活高效。
- 如果你的item有圆角,可以用
Path来绘制带圆角的背景矩形,避免和item形状冲突。 - 图标建议用矢量图(VectorDrawable),保证不同分辨率下显示清晰。
这样改完之后,就能实现和Google Inbox类似的左右滑不同效果啦!
内容的提问来源于stack exchange,提问作者BakaOne
相关产品推荐
相关产品推荐

