重写listview,横向滑动出现删除按钮,点击按钮删除item

2015-05-29 09:30

首先看一下效果图:
重写listview,横向滑动出现删除按钮,点击按钮删除item0

接下来看具体操作:

准备一个删除按钮的布局,新建button.xml文件,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>

    
<Button  xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="delete"/>

这个布局很简单,只有一个按钮而已。

接着创建MyLIstView继承自ListView,这就是我们自定义的View了,代码如下所示:

package com.example.animal;

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

public class MyListView extends ListView implements OnGestureListener,
		OnTouchListener {

	/**
	 * 删除按钮是否显示出来,默认是false
	 */
	boolean isDeleteShow = false;
	/**
	 * 点击的是哪个item
	 */
	int itemPosition;
	/**
	 * 删除按钮的视图
	 */
	View deleteButton;
	/**
	 * 点击的item的整行视图
	 */
	ViewGroup itemLayout;
	/**
	 * 响应OnGestureListener方法
	 */
	GestureDetector detector;
	/**
	 * 自定义的删除监听器
	 */
	onDeleteListener deleteListener;

	public MyListView(Context context, AttributeSet attrs) {
		super(context, attrs);
		detector=new GestureDetector(getContext(), this);
		setOnTouchListener(this);
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		if(isDeleteShow){
			// 如果删除按钮显示出来
			itemLayout.removeView(deleteButton);  
            deleteButton = null;  
            isDeleteShow = false;  
            return false;  
		}else{
			// 如果删除按钮没有显示出来
			return detector.onTouchEvent(event);
		}
	}

	@Override
	public boolean onDown(MotionEvent e) {
		if (isDeleteShow) {
			// 如果删除按钮显示出来

		} else {
			// 如果删除按钮没有显示出来
			itemPosition = pointToPosition((int) e.getX(), (int) e.getY());
		}
		return false;
	}

	@Override
	public void onShowPress(MotionEvent e) {
	}

	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		return false;
	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		return false;
	}

	@Override
	public void onLongPress(MotionEvent e) {
	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		//当删除按钮没有显示,并且横向滑动速度大于纵向滑动速度
		if (!isDeleteShow && Math.abs(velocityX) > Math.abs(velocityY)) {
			deleteButton = LayoutInflater.from(getContext()).inflate(
					R.layout.button, null);
			deleteButton.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					itemLayout.removeView(deleteButton);
					deleteButton=null;
					isDeleteShow=false;
					deleteListener.onDelete(itemPosition);
				}
			});
			//动态添加删除按钮到item视图上
			itemLayout = (ViewGroup) getChildAt(itemPosition
					- getFirstVisiblePosition());
			RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
					LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
			params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
			params.addRule(RelativeLayout.CENTER_VERTICAL);
			itemLayout.addView(deleteButton, params);
			isDeleteShow=true;
		}
		return false;
	}

	public void setDeleteListener(onDeleteListener listener){
		deleteListener=listener;
	}
	public interface onDeleteListener{
		void onDelete(int index);
			
		
	}
}



这里在MyListView构造方法中创建了一个GestureDetector实例用于监听手势,然后给MyLIstView注册了touch监听事件。然后在onTouch方法中判断,如果删除按钮已经显示,则将它移除,如果没有显示,就使用GestureDetector来处理当前手势。


当手指按下时,会调用OnGestureListener的onDown()方法,在这里通过pointToPosition()方法来判断出当前选中的是ListView的哪一行。当手指快速滑动时,会调用onFling()方法,在这里会去加载delete_button.xml这个布局,然后将删除按钮添加到当前选中的那一行item上。注意,我们还给删除按钮添加了一个点击事件,当点击了删除按钮时就会回调onDeleteListener的onDelete()方法,在回调方法中应该去处理具体的删除操作。




注意:删除listView中的一个项目,其实就是删除listView适配后的一个数据。


在activity_main中,引用自己创建的MyLIstView,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
 
    <com.example.animal.MyListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></com.example.animal.MyListView>
</LinearLayout>

在MainActivity里,就可以引用了。

package com.example.animal;

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

import com.example.animal.MyListView.onDeleteListener;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class MainActivity extends Activity {

	MyListView listView;
	MyAdapter myAdapter;
	ArrayList<String> arrayList = new ArrayList<String>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initArrayList();
		listView = (MyListView) findViewById(R.id.list);
		myAdapter = new MyAdapter(getApplicationContext(), arrayList);
		listView.setAdapter(myAdapter);
		listView.setDeleteListener(new onDeleteListener() {

			@Override
			public void onDelete(int index) {
				arrayList.remove(index);
				myAdapter.notifyDataSetChanged();
			}
		});

	}

	private void initArrayList() {
		arrayList.add("Content Item 1");
		arrayList.add("Content Item 2");
		arrayList.add("Content Item 3");
		arrayList.add("Content Item 4");
		arrayList.add("Content Item 5");
		arrayList.add("Content Item 6");
		arrayList.add("Content Item 7");
		arrayList.add("Content Item 8");
		arrayList.add("Content Item 9");
		arrayList.add("Content Item 10");
		arrayList.add("Content Item 11");
		arrayList.add("Content Item 12");
		arrayList.add("Content Item 13");
		arrayList.add("Content Item 14");
		arrayList.add("Content Item 15");
		arrayList.add("Content Item 16");
		arrayList.add("Content Item 17");
		arrayList.add("Content Item 18");
		arrayList.add("Content Item 19");
		arrayList.add("Content Item 20");
	}

}

class MyAdapter extends BaseAdapter {
	Context context;
	ArrayList<String> list;

	public MyAdapter(Context context, ArrayList<String> list) {
		this.context = context;
		this.list = list;
	}

	@Override
	public int getCount() {
		return 10;
	}

	@Override
	public Object getItem(int position) {
		return null;
	}

	@Override
	public long getItemId(int position) {
		return 0;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		View view;
		if (convertView == null) {
			view = LayoutInflater.from(context).inflate(R.layout.textv, null);
		} else {
			view = convertView;
		}
		TextView tv = (TextView) view.findViewById(R.id.text);
		tv.setText(list.get(position));
		return view;
	}

}


MainActivity里的内容很简单,我就不再解释了。
关于,listView里的小视图,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
     >
    
<TextView android:id="@+id/text"
    android:layout_width="wrap_content"
    android:layout_height="100dp"
    />
</RelativeLayout>


演示结束。

关于OnGestureListener和OnTouchListener,你可以点击查看

参考文章:http://blog.csdn.net/guolin_blog/article/details/17357967