自定义listView添加滑动删除功能

今天研究了一下android里面的手势,结合昨天学习的自定义View,做了一个自定义的listview,继承自listView,添加了条目的滑动手势操作,滑动后出现一个删除按钮,点击删除按钮,触发一个删除的事件,在事件中进行删除当选行的元素,刷新listview。

一共分为以下几步进行:

1、新建一个按钮的布局文件,用来作为动态添加的按钮:layout_button.xml

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

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

2、定义按钮显示,隐藏的动画效果,简单的缩放动画:

btn_hide.xml:

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

<scale xmlns:android="http://schemas.android.com/apk/res/android"  android:fromXScale="1.0"  android:toXScale="0"  android:fromYScale="1.0"  android:toYScale="1.0"  android:pivotX="100%"  android:pivotY="0"  android:duration="200"  />

btn_show.xml:

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

<scale xmlns:android="http://schemas.android.com/apk/res/android"  android:fromXScale="0"  android:toXScale="1.0"  android:fromYScale="1.0"  android:toYScale="1.0"  android:pivotX="100%"  android:pivotY="0"  android:duration="200"  />

3、自定义ListView,继承自listView,并实现OnTouchListener,OnGestureListener接口,代码就不一步一步写了,里面我尽可能的注释详细一些:MyListView.java

package com.example.viewtest;



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.view.animation.AnimationUtils; import android.widget.ListView; import android.widget.RelativeLayout;  /** * 项目名称:viewTest * 实现功能: 自定义ListView,增加滑动删除功能 * 类名称:MyListView * 类描述:(该类的主要功能) * 创建人:徐纪伟 * E-mail: [email protected] * 创建时间:2014年11月2日 下午3:37:40 * 修改人: * 修改时间: * 修改备注: * @version */ public class MyListView extends ListView implements OnTouchListener,OnGestureListener {    /**   * 手势识别类   */   private GestureDetector gestureDetector;     /**   * 滑动时出现的按钮   */   private View btnDelete;     /**   * listview的每一个item的布局   */   private ViewGroup viewGroup;   /**   * 选中的项   */   private int selectedItem;     /**   * 是否已经显示删除按钮   */   private boolean isDeleteShow;     /**   * 点击删除按钮时删除每一行的事件监听器   */   private OnItemDeleteListener onItemDeleteListener;   /**   * 构造函数,初始化手势监听器等   * @param context   * @param attrs   */   public MyListView(Context context, AttributeSet attrs) {    super(context, attrs);    gestureDetector = new GestureDetector(getContext(),this);    setOnTouchListener(this);   }     public void setOnItemDeleteListener(OnItemDeleteListener onItemDeleteListener) {    this.onItemDeleteListener = onItemDeleteListener;   }   @Override   public boolean onTouch(View v, MotionEvent event) {    //得到当前触摸的条目    selectedItem = pointToPosition((int)event.getX(), (int)event.getY());    //如果删除按钮已经显示,那么隐藏按钮,异常按钮在当前位置的绘制    if (isDeleteShow) {     btnHide(btnDelete);     viewGroup.removeView(btnDelete);     btnDelete = null;     isDeleteShow = false;     return false;    }else{     //如果按钮没显示,则触发手势事件     //由此去触发GestureDetector的事件,可以查看其源码得知,onTouchEvent中进行了手势判断,调用onFling     return gestureDetector.onTouchEvent(event);    }      }   @Override   public boolean onDown(MotionEvent e) {    //得到当前触摸的条目    if (!isDeleteShow) {     selectedItem = pointToPosition((int)e.getX(), (int)e.getY());    }    return true;   }   @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)) {     //在当前布局上,动态添加我们的删除按钮,设置按钮的各种参数、事件,按钮的点击事件响应我们的删除项监听器     btnDelete = LayoutInflater.from(getContext()).inflate(R.layout.layout_button, null);     btnDelete.setOnClickListener(new OnClickListener() {           @Override      public void onClick(View v) {       //btnHide(btnDelete);       viewGroup.removeView(btnDelete);       btnDelete = null;       isDeleteShow = false;  onItemDeleteListener.onItemDelete(selectedItem);      }     });     viewGroup = (ViewGroup)getChildAt(selectedItem - getFirstVisiblePosition());     RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);     layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);     layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);     btnDelete.setLayoutParams(layoutParams);     viewGroup.addView(btnDelete);     btnShow(btnDelete);     isDeleteShow = true;    }else{     setOnTouchListener(this);    }       return false;   }   /**     * @类名称: OnItemDeleteListener     * @描述: 删除按钮监听器     * @throws     * @author 徐纪伟     * 2014年11月9日上午11:25:37   */   public interface OnItemDeleteListener{    public void onItemDelete(int selectedItem);   }     /**    * @方法名称: btnShow  * @描述: 按钮显示时的动画  * @param @param v  * @return void  * @throws  * @author 徐纪伟  * 2014年11月9日 上午11:25:12  */ private void btnShow(View v){  v.startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.btn_show));  } /**  * @方法名称: btnHide  * @描述: 按钮隐藏时的动画  * @param @param v  * @return void  * @throws  * @author 徐纪伟  * 2014年11月9日 上午11:25:23  */ private void btnHide(View v){  v.startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.btn_hide));  }  }

4、使用方法,布局文件,activity,很简单activity_main.xml:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:id="@+id/main_layout"  android:layout_width="match_parent"  android:layout_height="match_parent" >  <com.example.viewtest.MyListView   android:id="@+id/my_listview"   android:layout_width="match_parent"   android:layout_height="match_parent">    </com.example.viewtest.MyListView> </RelativeLayout>

listview的每一个item的布局文件,一个textview,item.xml:

<?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/textView1"   android:layout_width="wrap_content"   android:layout_height="50dp"   android:text="TextView" />  </RelativeLayout>

activity,初始化listview,adapter的使用就不在介绍,跟普通的一样,唯一不同的就是,要给我们的自定义listview添加我们自定义的删除按钮单击事件,以此来响应我们的删除事件,MainActivity.java:

package com.example.viewtest;



import java.util.LinkedList; import java.util.List; import android.content.Context; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.example.viewtest.MyListView.OnItemDeleteListener; public class MainActivity extends ActionBarActivity {   /**  * 自定义listview对象  */  private MyListView myListview;  /**  * listView的数据集合  */  private List<String> contentList = new LinkedList<String>();  /**  * 自定义数据适配器  */  private MyAdapter adapter;  @Override  protected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);   setContentView(R.layout.activity_main);   //初始化数据   setData();   myListview = (MyListView)findViewById(R.id.my_listview);   adapter = new MyAdapter(this);   myListview.setAdapter(adapter);   //添加自定义listview的按钮单击事件,处理删除结果,和普通listview使用的唯一不同之处,   myListview.setOnItemDeleteListener(new OnItemDeleteListener() {    @Override    public void onItemDelete(int index) {     contentList.remove(index);     adapter.notifyDataSetChanged();    }   });  }  @Override  public boolean onCreateOptionsMenu(Menu menu) {     getMenuInflater().inflate(R.menu.main, menu);   return true;  }  @Override  public boolean onOptionsItemSelected(MenuItem item) {     int id = item.getItemId();   if (id == R.id.action_settings) {    return true;   }   return super.onOptionsItemSelected(item);  }   /**    * @类名称: MyAdapter    * @描述: 自定义数据适配器    * @throws    * @author 徐纪伟    * 2014年11月9日下午12:20:19  */  class MyAdapter extends BaseAdapter{     private Context context;   public MyAdapter(Context context) {    this.context = context;   }   @Override   public int getCount() {    // TODO Auto-generated method stub    return contentList.size();   }   @Override   public Object getItem(int position) {    // TODO Auto-generated method stub    return contentList.get(position);   }   @Override   public long getItemId(int position) {    // TODO Auto-generated method stub    return position;   }   @Override   public View getView(int position, View convertView, ViewGroup parent) {    if (convertView == null) {     convertView = LayoutInflater.from(context).inflate(R.layout.item, null);    }    TextView textView = (TextView)convertView.findViewById(R.id.textView1);    textView.setText(contentList.get(position));    return convertView;   }  }   /**   * @方法名称: setData   * @描述: 初始化数据   * @param   * @return void   * @throws   * @author 徐纪伟   * 2014年11月9日 下午12:20:32  */  private void setData() {     for (int i = 0; i < 30; i++) {    contentList.add("Item "+i);   }  } }

运行效果:

自定义listView添加滑动删除功能

再给button加上selector背景,更好看一些:selector_btn_red.xml

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

<selector xmlns:android="http://schemas.android.com/apk/res/android" > <item android:state_pressed="true" android:drawable="@drawable/btn_style_zero_pressed"></item> <item android:state_pressed="false" android:drawable="@drawable/btn_style_zero_normal"></item> </selector>

资源图片在附件源码中上传。

最终效果:

自定义listView添加滑动删除功能

图片显示的位置在自定义listview中可以调整。

你可能感兴趣的:(ListView)