• 自定义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: xujiwei558@126.com
     * 创建时间: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);  
        }
      }  
    
    }

    运行效果:

    再给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中可以调整。

  • 相关阅读:
    Vue2.0一个login跳转实例
    canvas动画—圆形扩散、运动轨迹
    根据地理信息绘画的html5 小游戏
    用vue开发一个猫眼电影web app
    微信小程序 iphone6 和 iphone6plus 如何设置rpx单位,通俗易懂的方法
    前端实例练习
    为表单加上即时通讯的能力
    MongoDB学习笔记4——GridFS基础
    剑指Offer(Java版)第十三题:请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。
    剑指Offer(Java版)第十一题
  • 原文地址:https://www.cnblogs.com/exmyth/p/4594359.html
Copyright © 2020-2023  润新知