Recycleview上拉刷新_下拉加载_侧滑删除加强篇

总有那么几个二比产品,让你上拉刷新下拉加载之后,又想让你可以侧滑删除,我想静静.
产品狗虽然可恨,可是我们还是得乖乖的去实现,没办法,谁让我们是打工的,加油骚年们.

看下我们的效果


这里写图片描述

首先定义我们最重要的一个侧滑处理类,使用ViewDragHelper来处理的.不懂的可以看下弘扬大神的博客


Android ViewDragHelper完全解析 自定义ViewGroup神器

package yuan.kuo.yu.view;

import android.content.Context;
import android.graphics.Rect;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;

/**
 * Created by yukuoyuan on 2017/3/10.
 * 这是一个可以侧滑菜单的条目的父布局
 */

public class SwipeRecycleviewItemLayout extends FrameLayout {


    private View menu;
    private View content;
    private final ViewDragHelper dragHelper;
    private boolean isOpen;
    private int currentState;

    /**
     * 构造方法
     *
     * @param context 上下文
     * @param attrs   属性集合
     */
    public SwipeRecycleviewItemLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        /**
         * 初始化我们自定义处理触摸事件的方法
         */
        dragHelper = ViewDragHelper.create(this, rightCallback);
    }

    private ViewDragHelper.Callback rightCallback = new ViewDragHelper.Callback() {

        // 触摸到View的时候就会回调这个方法。
        // return true表示抓取这个View。
        @Override
        public boolean tryCaptureView(View child, int pointerId) {
            return content == child;
        }

        /**
         * 重新处理子view的左侧
         * @param child
         * @param left
         * @param dx
         * @return
         */
        @Override
        public int clampViewPositionHorizontal(View child, int left, int dx) {
            return left > 0 ? 0 : left < -menu.getWidth() ? -menu.getWidth() : left;
        }

        /**
         * 当手指释放的时候回调
         * @param releasedChild
         * @param xvel
         * @param yvel
         */
        @Override
        public void onViewReleased(View releasedChild, float xvel, float yvel) {

            // x轴移动速度大于菜单一半,或者已经移动到菜单的一般之后,展开菜单
            if (isOpen) {
                if (xvel > menu.getWidth() || -content.getLeft() < menu.getWidth() / 2) {
                    close();
                } else {
                    open();
                }
            } else {
                if (-xvel > menu.getWidth() || -content.getLeft() > menu.getWidth() / 2) {
                    open();
                } else {
                    close();
                }
            }
        }

        /**
         * view 横向移动的范围
         * @param child
         * @return
         */
        @Override
        public int getViewHorizontalDragRange(View child) {
            return 1;
        }

        /**
         *view纵向移动的范围
         * @param child
         * @return
         */
        @Override
        public int getViewVerticalDragRange(View child) {
            return 1;
        }

        /**
         * 当ViewDragHelper状态发生变化的时候调用(IDLE,DRAGGING,SETTING[自动滚动时])
         * @param state
         */
        @Override
        public void onViewDragStateChanged(int state) {
            super.onViewDragStateChanged(state);
            currentState = state;
        }
    };

    /**
     * 处理触摸事件(交给draghelper去处理)
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        dragHelper.processTouchEvent(event);
        return true;
    }

    /**
     * 处理触摸事件
     *
     * @param ev
     * @return
     */
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return dragHelper.shouldInterceptTouchEvent(ev);
    }

    /**
     * 获取当前的状态
     *
     * @return
     */
    public int getState() {
        return currentState;
    }

    private Rect outRect = new Rect();

    public Rect getMenuRect() {
        menu.getHitRect(outRect);
        return outRect;
    }

    /**
     * 当绘制完毕调用的方法
     */
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        menu = getChildAt(0);
        content = getChildAt(1);
    }

    /**
     * 这是一个关闭菜单的方法
     */
    public void close() {
        dragHelper.smoothSlideViewTo(content, 0, 0);
        isOpen = false;
        invalidate();
    }

    /**
     * 这是一个打开菜单的方法
     */
    public void open() {
        dragHelper.smoothSlideViewTo(content, -menu.getWidth(), 0);
        isOpen = true;
        invalidate();
    }

    /**
     * 计算滚动事件
     */
    @Override
    public void computeScroll() {
        super.computeScroll();
        if (dragHelper.continueSettling(true)) {
            invalidate();
        }
    }

    /**
     * 设置点击事件
     *
     * @param l
     */
    @Override
    public void setOnClickListener(OnClickListener l) {
        content.setOnClickListener(l);
    }

    public boolean isOpen() {
        return this.isOpen;
    }
}

然后定义我们的两个布局

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="?android:colorBackground"
    android:layout_height="60dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/item_content"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#49ff0000"
            android:gravity="center"
            android:text="小雨来了"
            android:textColor="@android:color/white"
            android:textSize="16sp" />
    </RelativeLayout>
</FrameLayout>

带侧滑删除的类型

<?xml version="1.0" encoding="utf-8"?>
<yuan.kuo.yu.view.SwipeRecycleviewItemLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:background="?android:colorBackground">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="right"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/delete"
            android:layout_width="60dp"
            android:layout_height="match_parent"
            android:background="#FF6A6A"
            android:gravity="center"
            android:text="删除"
            android:textColor="#fff"
            android:textSize="18sp" />

        <TextView
            android:id="@+id/ok"
            android:layout_width="60dp"
            android:layout_height="match_parent"
            android:background="#e0e0e0"
            android:gravity="center"
            android:text="确定"
            android:textColor="#fff"
            android:textSize="16sp" />
    </LinearLayout>

    <include layout="@layout/item_content" />

</yuan.kuo.yu.view.SwipeRecycleviewItemLayout>

接下来看下我们的适配器

package cn.yu.yuan;

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by yukuo on 2016/4/30.
 */
public class DemoSwipeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<SwipeDate> list = new ArrayList<>();

    public DemoSwipeAdapter(List<SwipeDate> list) {
        this.list = list;
    }

    public void addReFreshData() {
        notifyDataSetChanged();
    }

    public void addRLoadMOreData() {
        notifyDataSetChanged();
    }

    /**
     * 删除一个数据的方法
     *
     * @param position 索引
     */
    // TODO 一定要按照这个方式写,不然会crash,希望你有更好的解决方案
    public void removeData(int position) {
        list.remove(position);
        notifyItemRemoved(position + 1);
        if (position != list.size()) {
            if (position == 0) {
                notifyDataSetChanged();
            } else if (position == (list.size() - 1)) {
                notifyItemRangeChanged(position, 0);
            } else {
                notifyItemRangeChanged(position, list.size() - position);
            }
        }
    }

    @Override
    public int getItemViewType(int position) {
        return list.get(position).type;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view;
        if (viewType == 1) {
            view = View.inflate(parent.getContext(), R.layout.item_swipe_menu, null);
            return new MySwipeMenuHolder(view);
        } else {
            view = View.inflate(parent.getContext(), R.layout.item_content, null);
            return new MyHolder(view);
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
        if (holder instanceof MyHolder) {
            MyHolder myHolder = (MyHolder) holder;
            myHolder.item_content.setText(list.get(position).name);
        } else if (holder instanceof MySwipeMenuHolder) {
            MySwipeMenuHolder myHolder = (MySwipeMenuHolder) holder;
            myHolder.item_content.setText(list.get(position).name + "######" + position);
            myHolder.item_content.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(v.getContext(), list.get(position).name, Toast.LENGTH_SHORT).show();
                }
            });
            myHolder.delete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    removeData(position);
                }
            });
        }
    }

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

    class MyHolder extends RecyclerView.ViewHolder {

        private final TextView item_content;

        public MyHolder(View itemView) {
            super(itemView);
            item_content = (TextView) itemView.findViewById(R.id.item_content);
        }
    }

    class MySwipeMenuHolder extends RecyclerView.ViewHolder {

        private final TextView delete;
        private final TextView ok;
        private final TextView item_content;

        public MySwipeMenuHolder(View itemView) {
            super(itemView);
            item_content = (TextView) itemView.findViewById(R.id.item_content);

            delete = (TextView) itemView.findViewById(R.id.delete);
            ok = (TextView) itemView.findViewById(R.id.ok);
        }
    }
}

ok,到此我们自定义的侧滑删除功能就实现了,其实并没有太多难点,主要是在viewDragHelper这个类里边

Demo地址
欢迎Fork和Star,如果有问题,记得留言反馈给我啊.谢谢

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容