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

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

     

       一共分为以下几步进行:

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

 

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <Button   
  3.     xmlns:android="http://schemas.android.com/apk/res/android"  
  4.     android:text="删除"  
  5.     android:layout_width="wrap_content"    
  6.     android:layout_height="wrap_content"   
  7.     android:id="@+id/btn1"/>  

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

 

    btn_hide.xml:

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <scale xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:fromXScale="1.0"     
  4.     android:toXScale="0"     
  5.     android:fromYScale="1.0"     
  6.     android:toYScale="1.0"     
  7.     android:pivotX="100%"    
  8.     android:pivotY="0"    
  9.     android:duration="200"  
  10.     />  
  11.      

    btn_show.xml:

 

 

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <scale xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:fromXScale="0"     
  4.     android:toXScale="1.0"     
  5.     android:fromYScale="1.0"     
  6.     android:toYScale="1.0"     
  7.     android:pivotX="100%"    
  8.     android:pivotY="0"    
  9.     android:duration="200"  
  10.     />  
  11.      

 

 

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

 

Java代码  收藏代码
  1.     package com.example.viewtest;  
  2.   
  3. import android.content.Context;  
  4. import android.util.AttributeSet;  
  5. import android.view.GestureDetector;  
  6. import android.view.GestureDetector.OnGestureListener;  
  7. import android.view.LayoutInflater;  
  8. import android.view.MotionEvent;  
  9. import android.view.View;  
  10. import android.view.View.OnTouchListener;  
  11. import android.view.ViewGroup;  
  12. import android.view.animation.AnimationUtils;  
  13. import android.widget.ListView;  
  14. import android.widget.RelativeLayout;  
  15.     /**       
  16.  * 项目名称:viewTest   
  17.  * 实现功能:  自定义ListView,增加滑动删除功能 
  18.  * 类名称:MyListView    
  19.  * 类描述:(该类的主要功能) 
  20.  * 创建人:徐纪伟  
  21.  * E-mail: xujiwei558@126.com 
  22.  * 创建时间:2014年11月2日 下午3:37:40    
  23.  * 修改人:    
  24.  * 修改时间:    
  25.  * 修改备注:    
  26.  * @version     
  27.  */  
  28. public class MyListView extends ListView implements OnTouchListener,OnGestureListener {  
  29.       
  30.         /** 
  31.          * 手势识别类 
  32.          */  
  33.         private GestureDetector gestureDetector;  
  34.           
  35.         /** 
  36.          * 滑动时出现的按钮 
  37.          */  
  38.         private View btnDelete;  
  39.           
  40.         /** 
  41.          * listview的每一个item的布局 
  42.          */  
  43.         private ViewGroup viewGroup;  
  44.         /** 
  45.          * 选中的项 
  46.          */  
  47.         private int selectedItem;  
  48.           
  49.         /** 
  50.          * 是否已经显示删除按钮 
  51.          */  
  52.         private boolean isDeleteShow;  
  53.           
  54.         /** 
  55.          * 点击删除按钮时删除每一行的事件监听器 
  56.          */  
  57.         private OnItemDeleteListener onItemDeleteListener;  
  58.   
  59.         /** 
  60.          * 构造函数,初始化手势监听器等 
  61.          * @param context 
  62.          * @param attrs 
  63.          */  
  64.         public MyListView(Context context, AttributeSet attrs) {  
  65.             super(context, attrs);  
  66.             gestureDetector = new GestureDetector(getContext(),this);  
  67.             setOnTouchListener(this);  
  68.         }  
  69.           
  70.   
  71.         public void setOnItemDeleteListener(OnItemDeleteListener onItemDeleteListener) {  
  72.             this.onItemDeleteListener = onItemDeleteListener;  
  73.         }  
  74.   
  75.   
  76.   
  77.         @Override  
  78.         public boolean onTouch(View v, MotionEvent event) {  
  79.             //得到当前触摸的条目  
  80.             selectedItem = pointToPosition((int)event.getX(), (int)event.getY());  
  81.             //如果删除按钮已经显示,那么隐藏按钮,异常按钮在当前位置的绘制  
  82.             if (isDeleteShow) {  
  83.                 btnHide(btnDelete);  
  84.                 viewGroup.removeView(btnDelete);  
  85.                 btnDelete = null;  
  86.                 isDeleteShow = false;  
  87.                 return false;  
  88.             }else{  
  89.                 //如果按钮没显示,则触发手势事件  
  90.                 //由此去触发GestureDetector的事件,可以查看其源码得知,onTouchEvent中进行了手势判断,调用onFling  
  91.                 return gestureDetector.onTouchEvent(event);  
  92.             }  
  93.               
  94.         }  
  95.   
  96.         @Override  
  97.         public boolean onDown(MotionEvent e) {  
  98.             //得到当前触摸的条目  
  99.             if (!isDeleteShow) {  
  100.                 selectedItem = pointToPosition((int)e.getX(), (int)e.getY());  
  101.             }  
  102.             return true;  
  103.         }  
  104.   
  105.         @Override  
  106.         public void onShowPress(MotionEvent e) {  
  107.               
  108.         }  
  109.   
  110.         @Override  
  111.         public boolean onSingleTapUp(MotionEvent e) {  
  112.             return false;  
  113.         }  
  114.   
  115.         @Override  
  116.         public boolean onScroll(MotionEvent e1, MotionEvent e2,  
  117.                 float distanceX, float distanceY) {  
  118.             return false;  
  119.         }  
  120.   
  121.         @Override  
  122.         public void onLongPress(MotionEvent e) {  
  123.               
  124.         }  
  125.   
  126.         /** 
  127.          * 滑动删除的主要响应方法。 
  128.          */  
  129.         @Override  
  130.         public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,  
  131.                 float velocityY) {  
  132.             //如果删除按钮没有显示,并且手势滑动符合我们的条件  
  133.             //此处可以根据需要进行手势滑动的判断,如限制左滑还是右滑,我这里是左滑右滑都可以  
  134.             if (!isDeleteShow && Math.abs(velocityX) > Math.abs(velocityY)) {  
  135.                 //在当前布局上,动态添加我们的删除按钮,设置按钮的各种参数、事件,按钮的点击事件响应我们的删除项监听器  
  136.                 btnDelete = LayoutInflater.from(getContext()).inflate(R.layout.layout_button, null);  
  137.                 btnDelete.setOnClickListener(new OnClickListener() {  
  138.                       
  139.                     @Override  
  140.                     public void onClick(View v) {  
  141.                         //btnHide(btnDelete);  
  142.                         viewGroup.removeView(btnDelete);    
  143.                         btnDelete = null;    
  144.                         isDeleteShow = false;    
  145.                         onItemDeleteListener.onItemDelete(selectedItem);    
  146.                     }  
  147.                 });  
  148.                 viewGroup = (ViewGroup)getChildAt(selectedItem - getFirstVisiblePosition());  
  149.                 RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  
  150.                 layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);    
  151.                 layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);    
  152.                 btnDelete.setLayoutParams(layoutParams);  
  153.                 viewGroup.addView(btnDelete);  
  154.                 btnShow(btnDelete);  
  155.                 isDeleteShow = true;   
  156.             }else{  
  157.                 setOnTouchListener(this);  
  158.             }  
  159.               
  160.             return false;  
  161.         }  
  162.   
  163.         /** 
  164.                 * @类名称: OnItemDeleteListener 
  165.                 * @描述: 删除按钮监听器 
  166.                 * @throws  
  167.                 * @author 徐纪伟 
  168.                 * 2014年11月9日上午11:25:37 
  169.          */  
  170.         public interface OnItemDeleteListener{  
  171.             public void onItemDelete(int selectedItem);  
  172.         }  
  173.           
  174.         /** 
  175.             * @方法名称: btnShow 
  176.             * @描述: 按钮显示时的动画 
  177.             * @param   @param v  
  178.             * @return void  
  179.             * @throws  
  180.             * @author 徐纪伟 
  181.             * 2014年11月9日 上午11:25:12 
  182.          */  
  183.         private void btnShow(View v){  
  184.             v.startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.btn_show));  
  185.         }  
  186.           
  187.         /** 
  188.             * @方法名称: btnHide 
  189.             * @描述: 按钮隐藏时的动画 
  190.             * @param   @param v  
  191.             * @return void  
  192.             * @throws  
  193.             * @author 徐纪伟 
  194.             * 2014年11月9日 上午11:25:23 
  195.          */  
  196.         private void btnHide(View v){  
  197.             v.startAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.btn_hide));  
  198.         }  
  199.       
  200. }  

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

 

 

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:id="@+id/main_layout"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent" >  
  5.   
  6.   
  7.      <com.example.viewtest.MyListView  
  8.          android:id="@+id/my_listview"  
  9.          android:layout_width="match_parent"  
  10.          android:layout_height="match_parent">  
  11.            
  12.      </com.example.viewtest.MyListView>  
  13. </RelativeLayout>  

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

 

 

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent" >  
  5.   
  6.     <TextView  
  7.         android:id="@+id/textView1"  
  8.         android:layout_width="wrap_content"  
  9.         android:layout_height="50dp"  
  10.         android:text="TextView" />  
  11.       
  12. </RelativeLayout>  

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

 

 

Java代码  收藏代码
  1. package com.example.viewtest;  
  2.   
  3. import java.util.LinkedList;  
  4. import java.util.List;  
  5.   
  6. import android.content.Context;  
  7. import android.os.Bundle;  
  8. import android.support.v7.app.ActionBarActivity;  
  9. import android.view.LayoutInflater;  
  10. import android.view.Menu;  
  11. import android.view.MenuItem;  
  12. import android.view.View;  
  13. import android.view.ViewGroup;  
  14. import android.widget.BaseAdapter;  
  15. import android.widget.TextView;  
  16.   
  17. import com.example.viewtest.MyListView.OnItemDeleteListener;  
  18.   
  19. public class MainActivity extends ActionBarActivity {  
  20.       
  21.     /** 
  22.      * 自定义listview对象 
  23.      */  
  24.     private MyListView myListview;  
  25.     /** 
  26.      * listView的数据集合 
  27.      */  
  28.     private List<String> contentList = new LinkedList<String>();  
  29.     /** 
  30.      * 自定义数据适配器 
  31.      */  
  32.     private MyAdapter adapter;  
  33.     @Override  
  34.     protected void onCreate(Bundle savedInstanceState) {  
  35.         super.onCreate(savedInstanceState);  
  36.         setContentView(R.layout.activity_main);  
  37.         //初始化数据  
  38.         setData();  
  39.         myListview = (MyListView)findViewById(R.id.my_listview);  
  40.         adapter = new MyAdapter(this);  
  41.         myListview.setAdapter(adapter);  
  42.         //添加自定义listview的按钮单击事件,处理删除结果,和普通listview使用的唯一不同之处,  
  43.         myListview.setOnItemDeleteListener(new OnItemDeleteListener() {    
  44.             @Override    
  45.             public void onItemDelete(int index) {    
  46.                 contentList.remove(index);    
  47.                 adapter.notifyDataSetChanged();    
  48.             }    
  49.         });    
  50.     }  
  51.   
  52.     @Override  
  53.     public boolean onCreateOptionsMenu(Menu menu) {  
  54.   
  55.           
  56.         getMenuInflater().inflate(R.menu.main, menu);  
  57.         return true;  
  58.     }  
  59.   
  60.     @Override  
  61.     public boolean onOptionsItemSelected(MenuItem item) {  
  62.           
  63.         int id = item.getItemId();  
  64.         if (id == R.id.action_settings) {  
  65.             return true;  
  66.         }  
  67.         return super.onOptionsItemSelected(item);  
  68.     }  
  69.       
  70.     /** 
  71.             * @类名称: MyAdapter 
  72.             * @描述: 自定义数据适配器 
  73.             * @throws  
  74.             * @author 徐纪伟 
  75.             * 2014年11月9日下午12:20:19 
  76.      */  
  77.     class MyAdapter extends BaseAdapter{  
  78.           
  79.         private Context context;  
  80.         public MyAdapter(Context context) {  
  81.             this.context = context;  
  82.         }  
  83.   
  84.         @Override  
  85.         public int getCount() {  
  86.             // TODO Auto-generated method stub  
  87.             return contentList.size();  
  88.         }  
  89.   
  90.         @Override  
  91.         public Object getItem(int position) {  
  92.             // TODO Auto-generated method stub  
  93.             return contentList.get(position);  
  94.         }  
  95.   
  96.         @Override  
  97.         public long getItemId(int position) {  
  98.             // TODO Auto-generated method stub  
  99.             return position;  
  100.         }  
  101.   
  102.         @Override  
  103.         public View getView(int position, View convertView, ViewGroup parent) {  
  104.             if (convertView == null) {  
  105.                 convertView = LayoutInflater.from(context).inflate(R.layout.item, null);  
  106.             }  
  107.             TextView textView = (TextView)convertView.findViewById(R.id.textView1);  
  108.             textView.setText(contentList.get(position));  
  109.             return convertView;  
  110.         }  
  111.     }  
  112.       
  113.     /** 
  114.         * @方法名称: setData 
  115.         * @描述: 初始化数据 
  116.         * @param     
  117.         * @return void  
  118.         * @throws  
  119.         * @author 徐纪伟 
  120.         * 2014年11月9日 下午12:20:32 
  121.      */  
  122.     private void setData() {    
  123.           
  124.         for (int i = 0; i < 30; i++) {  
  125.              contentList.add("Item "+i);    
  126.         }  
  127.     }    
  128.   
  129. }  

    运行效果:

 


 

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

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android" >  
  3.     <item android:state_pressed="true" android:drawable="@drawable/btn_style_zero_pressed"></item>  
  4.     <item android:state_pressed="false" android:drawable="@drawable/btn_style_zero_normal"></item>  
  5.   
  6. </selector>  

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

    最终效果: 



 

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

   

posted @ 2016-12-01 21:16  天涯海角路  阅读(191)  评论(0)    收藏  举报