Android列表侧滑删除就是这么简单

前言:今天突然想起来了列表的滑动删除功能,一些下拉刷新的框架也会带这个侧滑删除的功能,比如一些listview的和recycleview的刷新框架都有这个功能,我今天写这个博客的目的是如何不依赖这些框架也是实现侧滑删除,如果自己已经使用的列表框架没有侧滑删除怎么给单独加入侧滑删除功能。

概括:我今天写的这个文章就是讲的是怎么单独给列表加入侧滑删除功能,不去为了侧滑删除而依赖一个列表框架,就是说如果需要的话可以简简单单的在自己的列表中加入这个侧滑删除的功能。主要实现就是自定义列表条目的容器view,来实现对手势的监听,从而通过手势的侧滑实现删除按钮的出现效果。


好了,下面开始正文吧。。。


首先给出自定义条目容器控件的代码:


里面的注释请好好看看,有助于你快速的看懂这个类的实现,并且实现你的自定义!!

public class DragListItem extends LinearLayout {
    private Context mContext;
    private View mHidenDragView;
    private LinearLayout mContentView;//将包裹实际的内容
    private LinearLayout mHidenLayout;
    private Scroller mScroller;
    private int mLastX, mLastY;
    private int mDragOutWidth;//完全侧滑出来的距离
    private double mfraction = 0.75;//触发自动侧滑的临界点
    private boolean isDrag = false;

    public DragListItem(Context context) {
        super(context);
        mContext = context;
        initView();
    }
    public DragListItem(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        initView();
    }
    private void initView() {
        setOrientation(HORIZONTAL);

        //merge进来整个listItem,在这里可以自己定义删除按钮的显示的布局,随便按照的喜好修改都行
        mHidenDragView = View.inflate(mContext, R.layout.hide_drag_item, this);

        mContentView = (LinearLayout) mHidenDragView.findViewById(R.id.show_content_view);
        mHidenLayout = (LinearLayout) mHidenDragView.findViewById(R.id.hide_view);
        mScroller = new Scroller(mContext);

        //将隐藏的删除布局的宽度赋值给边界的值,根据自己的需要可以任意的修改
        mDragOutWidth = dip2px(mContext, 120);
    }
    public static int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
    /**
     * 根据传递进来的事件,在此进行侧滑逻辑的判断,从而实现侧滑时删除按钮滑出的效果功能
     */
    public void onDragTouchEvent(MotionEvent event) {
        if (isDrag) {//手指在横向滑动时设置条目不可点击
            setClickable(false);
        } else {
            setClickable(true);
        }
        int x = (int) event.getX();
        int y = (int) event.getY();
        int scrollX = getScrollX();//手机屏幕左上角x轴的值 - view的左上角x轴的值
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                hsaMove = true;
                int deltaX = x - mLastX;
                int deltaY = y - mLastY;

                //纵向的滑动大于横向的滑动时是不处罚侧滑效果的
                // 此处的加上100是为了让条目的侧滑更容易触发,根据自己的需要可以调整该值
                if (Math.abs(deltaX) + 100 < Math.abs(deltaY))
                {
                    break;
                }
                if (deltaX != 0) {//手指正在横向滑动
                    isDrag = true;
                    int newScrollX = scrollX - deltaX;//当这个值变小时,view视图向左滑动
                    if (newScrollX < 0) {//保持大于等于0,等于0时view左上角x值和屏幕左上角x值重合
                        newScrollX = 0;
                        setClickable(true);
                    } else if (newScrollX > mDragOutWidth) {//当到达隐藏布局的边界时 是不能再侧滑了
                        newScrollX = mDragOutWidth;
                    }
                    scrollTo(newScrollX, 0);
                }
                break;
            case MotionEvent.ACTION_UP:
                hsaMove = false;
            default:
                int finalScrollX = 0;

                //左滑到足够自动滑动的位置时可以自动滑出删除布局
                // ,否则就自动回缩隐藏删除布局
                if (scrollX > mDragOutWidth * mfraction) {
                    finalScrollX = mDragOutWidth;
                    autoScrollToX(finalScrollX, 500);
                } else {
                    rollBack();
                    isDrag = false;
                }
                break;
        }
        mLastX = x;
        mLastY = y;
    }
    private boolean hsaMove = false;//该条目是否已经监听过手势的滑动,用来作为判断是否进行条目左右滑动的条件之一
    public boolean isHsaMove() {
        return hsaMove;
    }
    public void setHsaMove(boolean hsaMove) {
        this.hsaMove = hsaMove;
    }
    public void setIsDrag(boolean isDrag) {
        this.isDrag = isDrag;
    }
    /**
     * 自动回滚到封闭状态
     */
    public void rollBack() {
        if (getScrollX() != 0) {
            autoScrollToX(0, 100);
            new Handler().postDelayed(new Runnable() {
                public void run() {
                    setClickable(true);
                    isDrag = false;//将状态置为false,没有侧滑出
                    hsaMove = false;//状态重置后将是否滑动过置为没有滑动过
                }
            }, 10);
        }
    }
    private void autoScrollToX(int finalX, int duration) {
        mScroller.startScroll(getScrollX(), 0, finalX - getScrollX(), 0, duration);
        invalidate();
    }
    public boolean getDragState() {
        return isDrag;
    }
    @Override
    public void computeScroll() {
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
        }
    }
    /**
     * 更改隐藏页的文字
     */
    public void setFirstHidenView(CharSequence charSequence) {
        TextView textView = (TextView) mHidenLayout.findViewById(R.id.hide_delete);
        textView.setText(charSequence);
    }
    /**
     * 给使用者添加隐藏页的视图(不仅仅是删除)
     */
    public void addHidenView(TextView view) {
        mHidenLayout.addView(view);
    }
    /**
     * 给使用者设置listItem的实际内容
     */
    public void setContentView(View view) {
        mContentView.addView(view);
    }
    public double getMfraction() {
        return mfraction;
    }
    public void setMfraction(double mfraction) {
        this.mfraction = mfraction;
    }
}

对这个控件做一下简单的解释:

在上面的自定义控件里面,通过注释大家可以清晰的看到是将原来的条目的布局包裹在该自定义的容器里面,然后拦截手指的事件做侧滑事件的处理,使得删除布局的显示和隐藏,就实现了侧滑的删除。

当然了,这个实现原理还是很简单的,看懂的人都可以根据自己的需要做定制的修改从而实现自己需要的效果和功能。

比如:隐藏的布局可以任意设置,所以不一定是删除功能,只要是需要侧滑实现的都是可以靠这个控件给快速简单的实现出来。


下面是这个控件需要加载的布局文件:(这是我项目的效果,不同的人可以根据自己的需要做不同的修改)

xml version="1.0" encoding="utf-8"?>
xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    /** 实际显示的内容/
            android:id="@+id/show_content_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        >
    
    /**隐藏在后面的删除/
            android:id="@+id/hide_view"
        android:layout_width="120dp"
        android:layout_height="match_parent"
        android:background="@android:color/holo_red_dark"
        android:orientation="horizontal">
                    android:id="@+id/hide_delete"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:gravity="center"
            android:text="删除"
            android:textSize="20sp" />
    

好了,这个自定义的控件的代码和布局文件已经提供给你了,原理我也已经说完了,就是靠这个 自定义的控件实现的侧滑删除效果。


下面就简单的以listview作为示例,给大家演示一下这个控件的简单用法:(在适配器里做这样的处理就好了

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder viewHolder;
    DragListItem dragListItem = (DragListItem) convertView;
    if (dragListItem == null) {
        View view = layoutInflater.inflate(R.layout.list_item_drag, parent, false);
        dragListItem = new DragListItem(mContext);
        dragListItem.setContentView(view);
        viewHolder = new ViewHolder(dragListItem);
        dragListItem.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) dragListItem.getTag();
    }
    dragListItem.rollBack();
    dragListItem.setOnClickListener(new View.OnClickListener() {//给条目添加点击事件
        @Override
        public void onClick(View v) {
        }
    });
    viewHolder.hideItem.setOnClickListener(new View.OnClickListener() {//给隐藏的布局设置点击事件 比如点击删除功能
         @Override
        public void onClick(View v) {
            Toast.makeText(mContext, "删除", Toast.LENGTH_SHORT).show();
        }
    });
    return dragListItem;
}

这样侧滑删除功能就在列表中给实现了!!!

虽然我是以listview作为的示例,但是只要是Android技术可以的同僚们,都能看出来这个实现可以在任何的列表中给集成进去从而简单快速的实现侧滑删除的效果!!


本篇到此结束    see  you







你可能感兴趣的:(温故而知新)