一个简单的自定义listview滑动删除

本人也是刚开始接触自定view,虽然之前用过不少自定view,但那都是直接copy别人的,作为一个Android工程师,自定view 还是必须要会的.

自定义view 分为三种:

  • 自绘控件
  • 组合控件
  • 继承控件

废话不说了直接上今天写的测试代码

  1. new一个类 继承listview ,实现两个事件监听器, 触摸事件:OnTouchListener ,和手势事件:OnGestureListener

关于GestureDetector.OnGestureListener 详解

package com.example.animate.test;

import android.content.Context;
import android.util.AttributeSet;
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;

/**
 * Created by Administrator on 2016/7/22 0022.
 */
public class Mylistview extends ListView implements View.OnTouchListener, GestureDetector.OnGestureListener {
    private GestureDetector gestureDetector;

    private OnDeleteListener listener;

    private View deleteButton;

    private ViewGroup itemLayout;

    private int selectedItem;

    private boolean isDeleteShown;

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

    public void setOnDeleteListener(OnDeleteListener l) {
        listener = l;
    }

    /*
         * 在onTouch()方法中,我们调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给GestureDetector
         * 来分析是否有合适的callback函数来处理用户的手势
         */
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        if (isDeleteShown) {
            itemLayout.removeView(deleteButton);
            deleteButton = null;
            isDeleteShown = false;
            return false;
        } else {
            return gestureDetector.onTouchEvent(event);
        }
    }

    // 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发
    @Override
    public boolean onDown(MotionEvent e) {
        if (!isDeleteShown) {
            selectedItem = pointToPosition((int) e.getX(), (int) e.getY());
        }
        return false;
    }

    /*
       * 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发
       * 注意和onDown()的区别,强调的是没有松开或者拖动的状态
       */    
    @Override
    public void onShowPress(MotionEvent e) {

    }

    // 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        return false;
    }
    // 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
        return false;
    }
    // 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发
    @Override
    public void onLongPress(MotionEvent e) {

    }
    // 用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        if (!isDeleteShown && Math.abs(velocityX) > Math.abs(velocityY)) {
            deleteButton = LayoutInflater.from(getContext()).inflate(
                    R.layout.delete_button, null);
            deleteButton.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    itemLayout.removeView(deleteButton);
                    deleteButton = null;
                    isDeleteShown = false;
                    listener.onDelete(selectedItem);
                }
            });
            itemLayout = (ViewGroup) getChildAt(selectedItem
                    - 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);
            isDeleteShown = true;
        }
        return false;
    }

    public interface OnDeleteListener {

        void onDelete(int index);

    }

}

2.然后就是在代码中添加自定义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"
   >

    <com.example.animate.test.Mylistview
        android:id="@+id/mylistview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"></com.example.animate.test.Mylistview>

</RelativeLayout>

3.适配器代码 ,跟Activity代码

package com.example.animate.test;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.ArrayList;

/**
 * Created by Administrator on 2016/7/22 0022.
 */
public class MylistviewAdpter extends BaseAdapter{
    public Context mcontext;
    public ArrayList<String>  mlist;
    public MylistviewAdpter(Context context, ArrayList<String> objects) {
      mcontext=context;
        mlist=objects;
    }

    @Override
    public int getCount() {
        return mlist.size();
    }

    @Override
    public Object getItem(int position) {
        return mlist.get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view;
        if (convertView == null) {
            view = LayoutInflater.from(mcontext).inflate(R.layout.list_item, null);
        } else {
            view = convertView;
        }
        TextView textView = (TextView) view.findViewById(R.id.text_view);
        textView.setText(mlist.get(position));

        return view;
    }
}
package com.example.animate.test;

import android.app.Activity;
import android.os.Bundle;

import java.util.ArrayList;

/**
 * Created by Administrator on 2016/7/22 0022.
 */
public class MainActivity3 extends Activity {
    private Mylistview myListView;

    private MylistviewAdpter adapter;

    private ArrayList<String> lists;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mylistview);
        lists = new ArrayList<String>();
        lists.add("我");
        lists.add("用");
        lists.add("双");
        lists.add("手");
        lists.add("成");
        lists.add("就");
        lists.add("你");
        lists.add("的");
        lists.add("梦");
        lists.add("想");
        myListView = (Mylistview) findViewById(R.id.mylistview);
        myListView.setOnDeleteListener(new Mylistview.OnDeleteListener() {
            @Override
            public void onDelete(int index) {
                lists.remove(index);
                adapter.notifyDataSetChanged();
            }
        });
        adapter = new MylistviewAdpter(this, lists);
        myListView.setAdapter(adapter);
    }


}

4.删除按钮布局 (删除按钮布局在 Mylistview中已被调用 ) 和 listview 的item 布局

<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/delete_button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="删除"
    android:background="@color/colorAccent" >

</Button>  
<?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"
    android:descendantFocusability="blocksDescendants"
    android:orientation="vertical">

    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_centerVertical="true"
        android:gravity="left|center_vertical"
        android:textColor="#000" />
</RelativeLayout>

介绍一个 android:descendantFocusability这个属性:
开发中很常见的一个问题,项目中的listview不仅仅是简单的文字,常常需要自己定义listview,自己的Adapter去继承BaseAdapter,在adapter中按照需求进行编写,问题就出现了,可能会发生点击每一个item的时候没有反应,无法获取的焦点。原因多半是由于在你自己定义的Item中存在诸如ImageButton,Button,CheckBox等子控件(也可以说是Button或者Checkable的子类控件),此时这些子控件会将焦点获取到,所以常常当点击item时变化的是子控件,item本身的点击没有响应。 这时候就可以使用descendantFocusability来解决啦

属性的值有三种:

    beforeDescendants:viewgroup会优先其子类控件而获取到焦点

    afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点

    blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点

一般我们直接用第三种

最后贴上效果图
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值