RecyclerView 实现滑动删除和拖拽功能
2017-04-08 15:04
666 查看
RecyclerView 实现滑动删除和拖拽功能
2017/02/28 ·技术分享 ·
RecyclerView
分享到:0
本文作者:
伯乐在线 -
Code4Android 。未经作者许可,禁止转载!
欢迎加入伯乐在线
专栏作者。
前言
从Android 5.0开始,谷歌推出了新的控件RecyclerView,相对于早它之前的ListView,优点多多,功能强大,也给我们的开发着提供了极大的便利,今天自己学习一下RecyclerView轻松实现滑动删除及拖拽的效果,如下图。相信研究过RecyclerView的同学,应该很清楚该怎么实现这样的效果,若是用ListView,这样的效果实现起来可能就有点麻烦,但是在强大的RecyclerView面前这样的的效果只需很少的代码,因为谷歌给我们提供了强大的工具类ItemTouchHelper,它已经处理了关于RecyclerView拖动和滑动的实现,并且我们可以在其中实现我们自己的动画,以及定制我们想要的效果。
ItemTouchHelper.Callback有几个重要的抽象方法,我们继承该抽象类,并重写抽象方法。它是我们实现滑动和拖拽重要的回调。
int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
1 | int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) |
ItemTouchHelper.UP //滑动拖拽向上方向
ItemTouchHelper.DOWN//向下
ItemTouchHelper.LEFT//向左
ItemTouchHelper.RIGHT//向右
ItemTouchHelper.START//依赖布局方向的水平开始方向
ItemTouchHelper.END//依赖布局方向的水平结束方向
1 2 3 4 5 6 | ItemTouchHelper.UP //滑动拖拽向上方向 ItemTouchHelper.DOWN//向下 ItemTouchHelper.LEFT//向左 ItemTouchHelper.RIGHT//向右 ItemTouchHelper.START//依赖布局方向的水平开始方向 ItemTouchHelper.END//依赖布局方向的水平结束方向 |
1 | boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) |
void onSwiped(RecyclerView.ViewHolder viewHolder, int direction)
1 | void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) |
上面三个方法是必须重写的方法,当然还有其它一些可供选择的方法。
/**
* Item是否支持长按拖动
*
* @return
* true 支持长按操作
* false 不支持长按操作
*/
boolean isLongPressDragEnabled()
/**
* Item是否支持滑动
*
* @return
* true 支持滑动操作
* false 不支持滑动操作
*/
boolean isItemViewSwipeEnabled()
/**
* 移动过程中绘制Item
*
* @param c
* @param recyclerView
* @param viewHolder
* @param dX
* X轴移动的距离
* @param dY
* Y轴移动的距离
* @param actionState
* 当前Item的状态
* @param isCurrentlyActive
* 如果当前被用户操作为true,反之为false
*/
onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | /** * Item是否支持长按拖动 * * @return * true 支持长按操作 * false 不支持长按操作 */ boolean isLongPressDragEnabled() /** * Item是否支持滑动 * * @return * true 支持滑动操作 * false 不支持滑动操作 */ boolean isItemViewSwipeEnabled() /** * 移动过程中绘制Item * * @param c * @param recyclerView * @param viewHolder * @param dX * X轴移动的距离 * @param dY * Y轴移动的距离 * @param actionState * 当前Item的状态 * @param isCurrentlyActive * 如果当前被用户操作为true,反之为false */ onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) |
功能实现
adapter=new CustomAdapter(getActivity(),strings);recycleview.setAdapter(adapter);
ItemTouchHelper.Callback callback=new RecycleItemTouchHelper(adapter);
ItemTouchHelper itemTouchHelper=new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(recycleview);
1 2 3 4 5 | adapter=new CustomAdapter(getActivity(),strings); recycleview.setAdapter(adapter); ItemTouchHelper.Callback callback=new RecycleItemTouchHelper(adapter); ItemTouchHelper itemTouchHelper=new ItemTouchHelper(callback); itemTouchHelper.attachToRecyclerView(recycleview); |
package com.example.xh.adapter;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.View;
import com.example.xh.R;
import com.example.xh.utils.MyApplication;
/**
* Created by xiehui on 2017/2/23.
*/
public class RecycleItemTouchHelper extends ItemTouchHelper.Callback{
private static final String TAG ="RecycleItemTouchHelper" ;
private final ItemTouchHelperCallback helperCallback;
public RecycleItemTouchHelper(ItemTouchHelperCallback helperCallback) {
this.helperCallback = helperCallback;
}
/**
* 设置滑动类型标记
*
* @param recyclerView
* @param viewHolder
* @return
* 返回一个整数类型的标识,用于判断Item那种移动行为是允许的
*/
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
Log.e(TAG, "getMovementFlags: " );
//START 右向左 END左向右 LEFT 向左 RIGHT向右 UP向上
//如果某个值传0,表示不触发该操作,次数设置支持上下拖拽,支持向右滑动
return makeMovementFlags(ItemTouchHelper.UP|ItemTouchHelper.DOWN,ItemTouchHelper.END );
}
/**
* Item是否支持长按拖动
*
* @return
* true 支持长按操作
* false 不支持长按操作
*/
@Override
public boolean isLongPressDragEnabled() {
return super.isLongPressDragEnabled();
}
/**
* Item是否支持滑动
*
* @return
* true 支持滑动操作
* false 不支持滑动操作
*/
@Override
public boolean isItemViewSwipeEnabled() {
return super.isItemViewSwipeEnabled();
}
/**
* 拖拽切换Item的回调
*
* @param recyclerView
* @param viewHolder
* @param target
* @return
* 如果Item切换了位置,返回true;反之,返回false
*/
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
Log.e(TAG, "onMove: " );
helperCallback.onMove(viewHolder.getAdapterPosition(),target.getAdapterPosition());
return true;
}
/**
* 滑动Item
*
* @param viewHolder
* @param direction
* Item滑动的方向
*/
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
Log.e(TAG, "onSwiped: ");
helperCallback.onItemDelete(viewHolder.getAdapterPosition());
}
/**
* Item被选中时候回调
*
* @param viewHolder
* @param actionState
* 当前Item的状态
* ItemTouchHelper.ACTION_STATE_IDLE 闲置状态
* ItemTouchHelper.ACTION_STATE_SWIPE 滑动中状态
* ItemTouchHelper#ACTION_STATE_DRAG 拖拽中状态
*/
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
super.onSelectedChanged(viewHolder, actionState);
}
public interface ItemTouchHelperCallback{
void onItemDelete(int positon);
void onMove(int fromPosition,int toPosition);
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | package com.example.xh.adapter; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; import android.util.Log; import android.view.View; import com.example.xh.R; import com.example.xh.utils.MyApplication; /** * Created by xiehui on 2017/2/23. */ public class RecycleItemTouchHelper extends ItemTouchHelper.Callback{ private static final String TAG ="RecycleItemTouchHelper" ; private final ItemTouchHelperCallback helperCallback; public RecycleItemTouchHelper(ItemTouchHelperCallback helperCallback) { this.helperCallback = helperCallback; } /** * 设置滑动类型标记 * * @param recyclerView * @param viewHolder * @return * 返回一个整数类型的标识,用于判断Item那种移动行为是允许的 */ @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { Log.e(TAG, "getMovementFlags: " ); //START 右向左 END左向右 LEFT 向左 RIGHT向右 UP向上 //如果某个值传0,表示不触发该操作,次数设置支持上下拖拽,支持向右滑动 return makeMovementFlags(ItemTouchHelper.UP|ItemTouchHelper.DOWN,ItemTouchHelper.END ); } /** * Item是否支持长按拖动 * * @return * true 支持长按操作 * false 不支持长按操作 */ @Override public boolean isLongPressDragEnabled() { return super.isLongPressDragEnabled(); } /** * Item是否支持滑动 * * @return * true 支持滑动操作 * false 不支持滑动操作 */ @Override public boolean isItemViewSwipeEnabled() { return super.isItemViewSwipeEnabled(); } /** * 拖拽切换Item的回调 * * @param recyclerView * @param viewHolder * @param target * @return * 如果Item切换了位置,返回true;反之,返回false */ @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { Log.e(TAG, "onMove: " ); helperCallback.onMove(viewHolder.getAdapterPosition(),target.getAdapterPosition()); return true; } /** * 滑动Item * * @param viewHolder * @param direction * Item滑动的方向 */ @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { Log.e(TAG, "onSwiped: "); helperCallback.onItemDelete(viewHolder.getAdapterPosition()); } /** * Item被选中时候回调 * * @param viewHolder * @param actionState * 当前Item的状态 * ItemTouchHelper.ACTION_STATE_IDLE 闲置状态 * ItemTouchHelper.ACTION_STATE_SWIPE 滑动中状态 * ItemTouchHelper#ACTION_STATE_DRAG 拖拽中状态 */ @Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { super.onSelectedChanged(viewHolder, actionState); } public interface ItemTouchHelperCallback{ void onItemDelete(int positon); void onMove(int fromPosition,int toPosition); } } |
positon)。到这里我们自定义的ItemTouchHelper.Callback创建完成。
上面完成后我们只需要在我们自定义的Adapter中实现RecycleItemTouchHelper.ItemTouchHelperCallback接口,然后在回调方法中更新界面,如下Apdater中回调方法实现。
@Override
public void onItemDelete(int positon) {
list.remove(positon);
notifyItemRemoved(positon);
}
@Override
public void onMove(int fromPosition, int toPosition) {
Collections.swap(list,fromPosition,toPosition);//交换数据
notifyItemMoved(fromPosition,toPosition);
}
1 2 3 4 5 6 7 8 9 10 11 | @Override public void onItemDelete(int positon) { list.remove(positon); notifyItemRemoved(positon); } @Override public void onMove(int fromPosition, int toPosition) { Collections.swap(list,fromPosition,toPosition);//交换数据 notifyItemMoved(fromPosition,toPosition); } |
好了到这里功能已经实现了,是不是发现代码很少,当然啰嗦的比较多而已。
功能升级
通过上面简单代码的实现,已经可以滑动删除和拖拽了,当然不满足的你可能发现滑动删除的时候没有动画没有背景,但是我想更改下背景并且在滑动的过程会出现一个删除的图标,给用户反馈,让其明白该操作是删除数据的。当然你还会想再删除的过程中增加一个动画。其实实现这个效果也并不是很麻烦,接下来新的方法实现登场。哦,不对,前面提到过的。onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive)
1 | onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) |
初始化
/**
* 移动过程中绘制Item
*
* @param c
* @param recyclerView
* @param viewHolder
* @param dX
* X轴移动的距离
* @param dY
* Y轴移动的距离
* @param actionState
* 当前Item的状态
* @param isCurrentlyActive
* 如果当前被用户操作为true,反之为false
*/
@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){
//dX大于0时向右滑动,小于0向左滑动
View itemView=viewHolder.itemView;//获取滑动的view
Resources resources= MyApplication.getAppContext().getResources();
Bitmap bitmap= BitmapFactory.decodeResource(resources, R.drawable.delete);//获取删除指示的背景图片
int padding =10;//图片绘制的padding
int maxDrawWidth=2*padding+bitmap.getWidth();//最大的绘制宽度
Paint paint=new Paint();
paint.setColor(resources.getColor(R.color.btninvalid));
int x=Math.round(Math.abs(dX));
int drawWidth=Math.min(x,maxDrawWidth);//实际的绘制宽度,取实时滑动距离x和最大绘制距离maxDrawWidth最小值
int itemTop=itemView.getBottom()-itemView.getHeight();//绘制的top位置
//向右滑动
if(dX>0){
//根据滑动实时绘制一个背景
c.drawRect(itemView.getLeft(),itemTop,drawWidth,itemView.getBottom(),paint);
//在背景上面绘制图片
if (x>padding){//滑动距离大于padding时开始绘制图片
//指定图片绘制的位置
Rect rect=new Rect();//画图的位置
rect.left=itemView.getLeft()+padding;
rect.top=itemTop+(itemView.getBottom()-itemTop-bitmap.getHeight())/2;//图片居中
int maxRight=rect.left+bitmap.getWidth();
rect.right=Math.min(x,maxRight);
rect.bottom=rect.top+bitmap.getHeight();
//指定图片的绘制区域
Rect rect1=null;
if (x
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | /** * 移动过程中绘制Item * * @param c * @param recyclerView * @param viewHolder * @param dX * X轴移动的距离 * @param dY * Y轴移动的距离 * @param actionState * 当前Item的状态 * @param isCurrentlyActive * 如果当前被用户操作为true,反之为false */ @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){ //dX大于0时向右滑动,小于0向左滑动 View itemView=viewHolder.itemView;//获取滑动的view Resources resources= MyApplication.getAppContext().getResources(); Bitmap bitmap= BitmapFactory.decodeResource(resources, R.drawable.delete);//获取删除指示的背景图片 int padding =10;//图片绘制的padding int maxDrawWidth=2*padding+bitmap.getWidth();//最大的绘制宽度 Paint paint=new Paint(); paint.setColor(resources.getColor(R.color.btninvalid)); int x=Math.round(Math.abs(dX)); int drawWidth=Math.min(x,maxDrawWidth);//实际的绘制宽度,取实时滑动距离x和最大绘制距离maxDrawWidth最小值 int itemTop=itemView.getBottom()-itemView.getHeight();//绘制的top位置 //向右滑动 if(dX>0){ //根据滑动实时绘制一个背景 c.drawRect(itemView.getLeft(),itemTop,drawWidth,itemView.getBottom(),paint); //在背景上面绘制图片 if (x>padding){//滑动距离大于padding时开始绘制图片 //指定图片绘制的位置 Rect rect=new Rect();//画图的位置 rect.left=itemView.getLeft()+padding; rect.top=itemTop+(itemView.getBottom()-itemTop-bitmap.getHeight())/2;//图片居中 int maxRight=rect.left+bitmap.getWidth(); rect.right=Math.min(x,maxRight); rect.bottom=rect.top+bitmap.getHeight(); //指定图片的绘制区域 Rect rect1=null; if (x |
float alpha = 1.0f - Math.abs(dX) / (float) itemView.getWidth();
itemView.setAlpha(alpha);
1 2 | float alpha = 1.0f - Math.abs(dX) / (float) itemView.getWidth(); itemView.setAlpha(alpha); |
源码传送门
打赏支持我写出更多好文章,谢谢!
打赏作者
打赏支持我写出更多好文章,谢谢!
任选一种支付方式1 赞
1 收藏
评论
关于作者:Code4Android
简介还没来得及写 :)
个人主页 ·
我的文章 ·
7 ·
相关文章推荐
- Android中RecyclerView实现滑动删除与拖拽功能
- Android View进阶之RecyclerView 实现滑动删除和拖拽功能
- [置顶] Android LRecyclerView实现Item侧滑菜单、长按拖拽Item、滑动删除Item等功能
- RecyclerView实现滑动删除和拖拽功能
- RecyclerView 实现滑动删除和拖拽功能
- Android LRecyclerView实现Item侧滑菜单、长按拖拽Item、滑动删除Item等功能
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能
- RecyclerView实现条目Item拖拽排序与滑动删除
- RecyclerView学习--item实现拖拽和滑动删除
- Android学习之ItemTouchHelper实现RecylerView的拖拽以及滑动删除功能
- 使用ItemTouchHelper轻松实现RecyclerView拖拽排序和滑动删除
- RecyclerView搭配ItemTouchHelper实现长按拖拽、滑动删除
- Android学习之ItemTouchHelper实现RecylerView的拖拽以及滑动删除功能
- RecyclerView借助ItemTouchHelper实现拖动和滑动删除功能
- Android一步一步带你实现RecyclerView的拖拽和侧滑删除功能
- RecyclerView实现滑动和拖拽功能(带小例子)
- Android一步步带你在RecyclerView上面实现"拖放"和"滑动删除"功能
- RecyclerView实现条目Item拖拽排序与滑动删除
- 使用ItemTouchHelper轻松实现RecyclerView拖拽排序和滑动删除
- RecyclerView实现条目Item拖拽排序与滑动删除