自定义RecyclerView实现侧滑删除

前言:

  项目源码下载地址:download.csdn.net/detail/mtx_…
  此篇主要是通过自动以RecyclerView,同过scrollTo()、Scroller来实现左划删除功能。

1.基础知识引入

scrollTo(int x,inty):
它是View中的方法,可以对View中的内容进行滚动,强调一下滑动的是view的“内容”,scrollTo()是让View相对于初始的位置滚动某段距离

RecyclerView实现左划删除

首选我来看Item的布局文件Recycler_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/item_root"
    >
 <TextView
     android:id="@+id/item_text"
     android:layout_width="match_parent"
     android:layout_height="40dp"
     android:layout_gravity="center"
     android:gravity="center"
     android:text="text" />

 <TextView
     android:id="@+id/item_del"
     android:layout_width="100dp"
     android:layout_height="fill_parent"
     android:background="#EE2C2C"
     android:text="删除"
     android:textSize="25dp"
     android:gravity="center" />
</LinearLayout>复制代码

item有两个水平的textView文件组成,第一个TextView是我们正常显示的Item,它的宽度占满屏幕,第二TextView就是我们的删除按钮,它被隐藏在屏幕之外。下面在看看Adapter部分CustomAdapter.java。

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder> {
    private List<String> mDatas;

    public CustomAdapter(List<String> mDatas, Context mContext) {
        this.mDatas = mDatas;
    }

    @Override
    public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false);
        return new CustomViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final CustomViewHolder holder, final int position) {
        holder.textView.setText(mDatas.get(position));
    }

    @Override
    public int getItemCount() {
        return mDatas.size();
    }

    class CustomViewHolder extends RecyclerView.ViewHolder {
        TextView textView;
        TextView deleteView;

        public CustomViewHolder(View itemView) {
            super(itemView);
            textView = (TextView) itemView.findViewById(R.id.item_text);
            deleteView = (TextView) itemView.findViewById(R.id.item_del);
        }
    }
}复制代码

这个比较简单,没啥可说的,下面我来来看看我的重点部分自定义的CustomRecyclerView类的实现

public class CustomRecyclerView extends RecyclerView{
    //item的根布局
    private LinearLayout itemRoot;
    //上一次滑动的Item根布局
    private LinearLayout itemRootLast;
    //上次X轴的滑动坐标
    private int mlastX = 0;
    //上次Y轴的滑动坐标
    private int mlastY = 0;
    //滑动的最大距离
    private final int MAX_WIDTH = 100;
    private Context mContext;
    private Scroller mScroller;

    public CustomRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        mScroller = new Scroller(context, new LinearInterpolator(context, null));
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int maxLength = dipToPx(mContext, MAX_WIDTH);
        int x = (int) event.getX();
        int y = (int) event.getY();
        final int  position;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                //恢复上一次侧滑的ITEM
                if(itemRootLast !=null){
                    itemRootLast.scrollTo(0, 0);
                    invalidate();
                }
                //根据点击的坐标获取那个Item被点击了
                View view  = findChildViewUnder(x, y);
                if(view == null){
                    return false;
                }
                final CustomAdapter.CustomViewHolder viewHolder = (CustomAdapter.CustomViewHolder) getChildViewHolder(view);
                itemRootLast = itemRoot = (LinearLayout) viewHolder.textView.getParent();

                 position= viewHolder.getAdapterPosition();
                if(mOnItemClickListener !=null){
                    viewHolder.deleteView.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            mOnItemClickListener.onClick(viewHolder.itemView,position);
                        }
                    });
                }
            }
            break;
            case MotionEvent.ACTION_MOVE: {
                if(itemRoot ==null){
                    return  false;
                }
                if(  Math.abs(mlastX -x)>0 && Math.abs(mlastX -x) > Math.abs(mlastY-y)){
                    int scrollX = itemRoot.getScrollX();
                    int newScrollX = scrollX + mlastX - x;
                    if (newScrollX < 0) {
                        newScrollX = 0;
                    } else if (newScrollX > maxLength) {
                        newScrollX = maxLength;
                    }
                    itemRoot.scrollTo(newScrollX, 0);
                }


            }
            break;
            case MotionEvent.ACTION_UP: {
                if(itemRoot ==null){
                    return  false;
                }
                int scrollX = itemRoot.getScrollX();
                int newScrollX = scrollX + mlastX - x;
                if (scrollX > maxLength / 2) {
                    newScrollX = maxLength;
                } else {
                    newScrollX = 0;
                }
                mScroller.startScroll(scrollX, 0, newScrollX - scrollX, 0);
                invalidate();
            }
            break;
        }
        mlastX = x;
        mlastY = y;
        return super.onTouchEvent(event);
    }

    private int dipToPx(Context context, int dip) {
        return (int) (dip * context.getResources().getDisplayMetrics().density + 0.5f);
    }

    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            itemRoot.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            if(itemRootLast !=null){
                itemRootLast.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            }
        }
        invalidate();
    }

    private OnItemClickListener mOnItemClickListener;
    public interface OnItemClickListener{
        void onClick(View view,int position);
    }

    public  void setOnItemClickListenre(OnItemClickListener mOnItemClickListener){
        this.mOnItemClickListener = mOnItemClickListener;
    }
}复制代码

我来来详细看一下上面的代码:


首选在MotionEvent.ACTION_DOWN事件发生时,如果上次有Item已经侧滑出了,这里就让它恢复正常的显示,接着看
我们通过findChildViewUnder(x, y)方法来实现根据当前点击的坐标值,得到被点击的Item的view,这一步是很关键的,接着我们通过刚才得到view获取到我们的viewHolder对象,拿到它我们就好办了,我们就可以得到点击Item的position等。

我们在MotionEvent.ACTION_MOVE事件中去根据手指滑动的距离来实时处理View的滑动

MotionEvent.ACTION_UP事件中,如果此时滑动的距离大于最大滑动距离的一半,我们就让整个按钮都滑动出来,反之我就让它恢复原来的状态.

删除按钮监听在ACTION_DOWN事件中绑定监听事件即可,监听接口如下

我们在MainActivity中实现给就可就Ok了

项目源码下载地址: download.csdn.net/detail/mtx_…
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值