这里只实现当有滑动速度时才会出现删除按钮,而不是像qq那样随着滑动一点一点出来的,qq那个后面再研究。

先看自定义的View的代码:

package com.hardy.person.housingestate.activities;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.hardy.person.housingestate.R;

/**
 * @author 马鹏昊
 * @date {2016-10-12}
 * @des 自定义左滑删除ListView
 * @updateAuthor
 * @updateDate
 * @updateDes
 */
public class MyListView extends ListView implements View.OnTouchListener,GestureDetector.OnGestureListener{

    private String TAG = "MyListView";
    //GestureDetector对象,注意要使用android.view.GestureDetector这个包下的
    private GestureDetector gestureDetector ;
    //自定义删除回调接口
    private OnDeleteListener listener;
    //删除按钮
    private View deleteButton;
    //触发左滑事件的Item
    private ViewGroup itemLayout;
    //记录触发触摸事件的点是属于adapter哪个项(由pointToPosition方法获得)
    private int selectedItem;
    //标志着删除按钮是否已经出现
    private boolean isDeleteShown;

    public MyListView(Context context) {
        super(context);
    }
    public MyListView(Context context,AttributeSet set) {
        super(context, set);
        //第二个参数是OnGestureListener对象
        gestureDetector = new GestureDetector(getContext(),this);
        //一开始触摸事件会先被OnTouchListener捕获,在onTouch()方法里去分配事件给GestureDetector,他才会有资格处理
        setOnTouchListener(this);
    }

    @Override
    public boolean onDown(MotionEvent e) {
        //测试三个方法的作用
        //pointToPosition(x ,y )方法是得到指定的x、y点的Item在adapter中的位置
        int po = pointToPosition((int) e.getX(), (int) e.getY());
        Log.d(TAG, "pointToPosition()返回的值:   " + po);

        //getFirstVisiblePosition()方法是得到屏幕中可见的第一个Item在adapter中的位置
        int firstVisiblePosition = getFirstVisiblePosition();
        Log.d(TAG, "getFirstVisiblePosition()返回的值:   " + firstVisiblePosition);
        int index = po - firstVisiblePosition ;
        Log.d(TAG, "pointToPosition()返回的值 - getFirstVisiblePosition()返回的值:   "+index);

        //getChildAt(index)方法是得到在屏幕中可见的这些Item中的index位置的Item,index不是在adapter中的位置,而是屏幕中可见的Item的位置
        TextView textView = (TextView) getChildAt(index);
        Log.d(TAG, "得到的ItemView的值:   " + textView.getText().toString());

        //如果删除按钮还不可见,得到点击的是在adapter中的位置
        if (!isDeleteShown) {
            selectedItem = pointToPosition((int) e.getX(), (int) e.getY());
        }
        return false;
    }

    //设置删除listener
    public void setOnDeleteListener(OnDeleteListener l) {
        listener = l;
    }

    //只要是按下没有抬起时触发,而onLongPress是当按住到达一定时间才能触发
    @Override
    public void onShowPress(MotionEvent e) {
    }

    //没有滑动,单击up时触发
    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }

    //当滑动时触发,并且distanceX和distanceY是上一次触发onScroll时的x、y到此次onScroll时的相应的距离,并不是到onDown时的相应距离
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        return false;
    }

    //毋庸置疑,当长按时触发
    @Override
    public void onLongPress(MotionEvent e) {
    }

    //当滑动的事件up时有加速度时触发
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        //如果删除按钮还不可见,并且x方向的加速度大于y方向的加速度则证明是横行滑动的,则显示删除按钮
        if (!isDeleteShown && Math.abs(velocityX) > Math.abs(velocityY)) {
            //通过inflater得到删除按钮
            deleteButton = LayoutInflater.from(getContext()).inflate(
                    R.layout.delete_button, null);
            //添加点击事件
            deleteButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    //从触发左滑事件的Item中移除掉删除按钮
                    itemLayout.removeView(deleteButton);
                    deleteButton = null;
                    //标志删除按钮不可见
                    isDeleteShown = false;
                    //执行删除时你要做的回调方法(移除该Item)
                    listener.onDelete(selectedItem);
                }
            });
            //找到触发左滑事件的Item
            itemLayout = (ViewGroup) getChildAt(selectedItem
                    - getFirstVisiblePosition());
            //设置要添加的删除按钮的参数和对齐方式
            RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
            //addRule()方法设置layout动词,可以理解为设置对齐方式
            params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
            params.addRule(RelativeLayout.CENTER_VERTICAL);
//            //设置要添加的删除按钮的参数和对齐方式
//            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
//                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
            //给该Item添加删除按钮
            itemLayout.addView(deleteButton, params);
            //标志删除按钮可见
            isDeleteShown = true;
        }
        return false;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        //如果删除按钮现在正可见,那么本次点击后,删除按钮隐藏
        if (isDeleteShown) {
            itemLayout.removeView(deleteButton);
            deleteButton = null;
            //标志删除按钮不可见
            isDeleteShown = false;
            return false;
        } else {
            //否则把触摸事件交给GestureDetector去处理左滑事件
            return gestureDetector.onTouchEvent(event);
        }
    }

    //删除回调接口
    public interface OnDeleteListener {

        void onDelete(int index);

    }

}

仔细看注释就能明白。

特意说一下:

触摸事件首先会被onTouchListener捕获,所以GestureDetector要想处理触摸事件必须在onTouch()方法里被分配了事件才行,所以整个事件的入口在onTouch()。

//否则把触摸事件交给GestureDetector去处理左滑事件
return gestureDetector.onTouchEvent(event);

Activity里设置删除监听方法和adapter即可:

final List<String> contentList = new ArrayList<>();
contentList.add("Content Item 1");
contentList.add("Content Item 2");
contentList.add("Content Item 3");
contentList.add("Content Item 4");
contentList.add("Content Item 5");
contentList.add("Content Item 6");
contentList.add("Content Item 7");
contentList.add("Content Item 8");
contentList.add("Content Item 9");
contentList.add("Content Item 10");
contentList.add("Content Item 11");
contentList.add("Content Item 12");
contentList.add("Content Item 13");
contentList.add("Content Item 14");
contentList.add("Content Item 15");
contentList.add("Content Item 16");
contentList.add("Content Item 17");
contentList.add("Content Item 18");
contentList.add("Content Item 19");
contentList.add("Content Item 20");
final ArrayAdapter arrayAdapter = new ArrayAdapter(this,R.layout.asdasdasd,R.id.text,contentList);
MyListView myListView = (MyListView) findViewById(R.id.asd);
myListView.setOnDeleteListener(new MyListView.OnDeleteListener() {
    @Override
    public void onDelete(int index) {
        contentList.remove(index);
        arrayAdapter.notifyDataSetChanged();
    }
});
myListView.setAdapter(arrayAdapter);

ok!完工!!