android---RecycleView使用ItemTouchHelper实现拖拽和侧滑删除

来源:互联网 发布:java多线程入门书籍 编辑:程序博客网 时间:2024/05/16 15:23

我之前就写过关于手势拖动的文章比如这个
还有这个滑动
这里今天我介绍下recycleview中的滑动,recycleview为我们提供了提供了强大的工具类ItemTouchHelper,它已经处理了关于RecyclerView拖动和滑动的实现,既然都已经有这个了那么我们的思路就很简单了加个回调,滑动效果结束后触发不就好了。

最近开始用gif录制了 上图
这里写图片描述
我们先看下这个ItemTouchHelper处理滑动的方法

    @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.LEFT|ItemTouchHelper.END);    }

这里我可以看到

        return makeMovementFlags(ItemTouchHelper.UP|ItemTouchHelper.DOWN,ItemTouchHelper.LEFT|ItemTouchHelper.END);

这个方法控制我们的滑动和拖动(这里的拖动是只长点击之后)

ItemTouchHelper.UP  //滑动拖拽向上方向ItemTouchHelper.DOWN//向下ItemTouchHelper.LEFT//向左ItemTouchHelper.RIGHT//向右ItemTouchHelper.START//依赖布局方向的水平开始方向ItemTouchHelper.END//依赖布局方向的水平结束方向

好了改说下滑动结束的方法

  public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction)

这里第二个参数是方向 我们可以根据这个处理不同的事件

下面的是拖动结束方法

 public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target)

还有个回调

   public interface ItemTouchHelperCallback{        void onItemDelete(int positon);        void onMove(int fromPosition,int toPosition);    }

那么这个类的代码给你们吧 (我觉得我描述的能力差了点)

package viewpage.yundong.com.recycleviewhuadong;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;/** * Created by Administrator on 2017/3/9. */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.LEFT|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: "+direction);        if (direction==ItemTouchHelper.END){            helperCallback.onItemDelete(viewHolder.getAdapterPosition());        }else if (direction==ItemTouchHelper.LEFT){            Log.e(TAG, "这是向左滑动操作" );        }    }    /**     * 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);    }}

然后是使用方法

        ItemTouchHelper.Callback callback=new RecycleItemTouchHelper(itemAdapter);        ItemTouchHelper itemTouchHelper=new ItemTouchHelper(callback);        itemTouchHelper.attachToRecyclerView(recycle);

当然 这里你的适配器也要写了 因为要控制数据变化

package viewpage.yundong.com.recycleviewhuadong;import android.content.Context;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import java.util.Collections;import java.util.List;/** * Created by Administrator on 2017/3/10. */public class ItemAdapter extends RecyclerView.Adapter implements RecycleItemTouchHelper.ItemTouchHelperCallback{    private Context context;    private List<String>list;    private LayoutInflater layoutInflater;    public ItemAdapter( Context context,List<String>list){        this.context=context;        this.list=list;        layoutInflater=LayoutInflater.from(context);    }    @Override    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        View view=layoutInflater.inflate(R.layout.item,parent, false);        return new ItemViewHolder(view);    }    @Override    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {        ItemViewHolder itemViewHolder= (ItemViewHolder) holder;        itemViewHolder.textView.setText(list.get(position));        ViewGroup.LayoutParams layoutParams=itemViewHolder.itemView.getLayoutParams();        layoutParams.height=ViewGroup.LayoutParams.WRAP_CONTENT;        itemViewHolder.itemView.setLayoutParams(layoutParams);    }    @Override    public int getItemCount() {        return list.size();    }    @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);    }    static class ItemViewHolder extends RecyclerView.ViewHolder{        private TextView textView;        public ItemViewHolder(View itemView) {            super(itemView);            textView= (TextView) itemView.findViewById(R.id.text_view);        }    }}

当然这我们还可以添加动画效果 ItemTouchHelper.ACTION_STATE_SWIPE 滑动中状态
在这个状态下绘制就有效果了
这里写图片描述
就是在

  /**     * 移动过程中绘制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) {        Log.e("滑动",dX+"==="+dY+"==="+actionState);        //滑动时自己实现背景及图片        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.ic_launcher);//获取删除指示的背景图片            int padding =10;//图片绘制的padding            int maxDrawWidth=2*padding+bitmap.getWidth();//最大的绘制宽度            Paint paint=new Paint();            paint.setColor(resources.getColor(R.color.colorPrimaryDark));            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<maxRight){                        rect1=new Rect();//不能再外面初始化,否则dx大于画图区域时,删除图片不显示                        rect1.left=0;                        rect1.top = 0;                        rect1.bottom=bitmap.getHeight();                        rect1.right=x-padding;                    }                    c.drawBitmap(bitmap,rect1,rect,paint);                }                //绘制时需调用平移动画,否则滑动看不到反馈                itemView.setTranslationX(dX);            }else {                //根据滑动实时绘制一个背景                c.drawRect(itemView.getRight()-drawWidth,itemTop,itemView.getRight(),itemView.getBottom(),paint);                //在背景上面绘制图片                if (x>padding){//滑动距离大于padding时开始绘制图片                    //指定图片绘制的位置                    Rect rect=new Rect();//画图的位置                    rect.right=itemView.getRight()-padding;                    rect.top=itemTop+(itemView.getBottom()-itemTop-bitmap.getHeight())/2;//图片居中                    int maxLeft=rect.right-bitmap.getWidth();                    rect.left=Math.max(itemView.getRight()-x,maxLeft);                    rect.bottom=rect.top+bitmap.getHeight();                    //指定图片的绘制区域  这里是对图片的剪裁                    Rect rect1=null;                    Log.e("这里执行到没",Math.max(itemView.getRight()-x-padding,maxLeft)+"==="+(bitmap.getWidth()-x+padding)+"====padding"+padding);                    if ((itemView.getRight()-x-padding)>maxLeft){                        Log.e("这里执行到没1111",(itemView.getRight()-x-padding)+"===="+maxLeft);                        rect1=new Rect();//不能再外面初始化,否则dx大于画图区域时,删除图片不显示                        rect1.left=bitmap.getWidth()-x+padding;                        rect1.top = 0;                        rect1.bottom=bitmap.getHeight();                        rect1.right=bitmap.getWidth()+padding;                    }                    c.drawBitmap(bitmap,rect1,rect,paint);                }                //绘制时需调用平移动画,否则滑动看不到反馈                itemView.setTranslationX(dX);            }        }else {            //拖动时有系统自己完成            super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);        }    }

这个你就也是在继承了ItemTouchHelper.Callback的类里加入即可

tip:我这里没写左滑的删除事件,就是做对比而已觉得不舒服在

  public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {        Log.e(TAG, "onSwiped: "+direction);        if (direction==ItemTouchHelper.END){            helperCallback.onItemDelete(viewHolder.getAdapterPosition());        }else if (direction==ItemTouchHelper.LEFT){            Log.e(TAG, "这是向左滑动操作" );        }    }

改下就好了

0 0
原创粉丝点击