这里只实现当有滑动速度时才会出现删除按钮,而不是像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!完工!!