ListView滑动删除 ,仿腾讯QQ

转载请表明出处:

在CSDN上开了很多大神们的文章,感觉受益良多,也非常欣赏大家的分享态度,所以决定开始写Blog,给大家分享自己的心得。

本来准备在ListView的每个Item的布局上设置一个隐藏的Button,当滑动的时候显示。但是因为每次只要存在一个Button,发现每个Item上的Button相互间不好控制。所以决定继承ListView然后结合PopupWindow。

首先是布局文件:

delete_btn.xml:这里只需要一个Button

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=""android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical" ><Buttonandroid:id="@+id/id_item_btn"android:layout_width="60dp"android:singleLine="true"android:layout_height="wrap_content"android:text="删除"android:background="@drawable/d_delete_btn"android:textColor="#ffffff"android:paddingLeft="15dp"android:paddingRight="15dp"android:layout_alignParentRight="true"android:layout_centerVertical="true"android:layout_marginRight="15dp"/></LinearLayout> 主布局文件:activity_main.xml,ListView的每个Item的样式直接使用了系统的android.R.layout.simple_list_item_1<RelativeLayout xmlns:android=""xmlns:tools=""android:layout_width="match_parent"android:layout_height="match_parent" ><com.example.listviewitemslidedeletebtnshow.QQListViewandroid:id="@+id/id_listview"android:layout_width="fill_parent"android:layout_height="wrap_content" ></com.example.listviewitemslidedeletebtnshow.QQListView></RelativeLayout>接下来看看QQListView的实现:package com.example.listviewitemslidedeletebtnshow;import android.content.Context;import android.util.AttributeSet;import android.view.Gravity;import android.view.LayoutInflater;import android.view.MotionEvent;import android.view.View;import android.view.ViewConfiguration;import android.widget.Button;import android.widget.LinearLayout;import android.widget.ListView;import android.widget.PopupWindow;public class QQListView extends ListView{private static final String TAG = "QQlistView";// private static final int VELOCITY_SANP = 200;// private VelocityTracker mVelocityTracker;/** * 用户滑动的最小距离 */private int touchSlop;/** * 是否响应滑动 */private boolean isSliding;/** * 手指按下时的x坐标 */private int xDown;/** * 手指按下时的y坐标 */private int yDown;/** * 手指移动时的x坐标 */private int xMove;/** * 手指移动时的y坐标 */private int yMove;private LayoutInflater mInflater;private PopupWindow mPopupWindow;private int mPopupWindowHeight;private int mPopupWindowWidth;private Button mDelBtn;/** * 为删除按钮提供一个回调接口 */private DelButtonClickListener mListener;/** * 当前手指触摸的View */private View mCurrentView;/** * 当前手指触摸的位置 */private int mCurrentViewPos;/** * 必要的一些初始化 * * @param context * @param attrs */public QQListView(Context context, AttributeSet attrs){super(context, attrs);mInflater = LayoutInflater.from(context);touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();View view = mInflater.inflate(R.layout.delete_btn, null);mDelBtn = (Button) view.findViewById(R.id.id_item_btn);mPopupWindow = new PopupWindow(view, LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);/** * 先调用下measure,否则拿不到宽和高 */mPopupWindow.getContentView().measure(0, 0);mPopupWindowHeight = mPopupWindow.getContentView().getMeasuredHeight();mPopupWindowWidth = mPopupWindow.getContentView().getMeasuredWidth();}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev){int action = ev.getAction();int x = (int) ev.getX();int y = (int) ev.getY();switch (action){case MotionEvent.ACTION_DOWN:xDown = x;yDown = y;/*** 如果当前popupWindow显示,则直接隐藏,然后屏蔽ListView的touch事件的下传*/if (mPopupWindow.isShowing()){dismissPopWindow();return false;}// 获得当前手指按下时的item的位置mCurrentViewPos = pointToPosition(xDown, yDown);// 获得当前手指按下时的itemView view = getChildAt(mCurrentViewPos – getFirstVisiblePosition());mCurrentView = view;break;case MotionEvent.ACTION_MOVE:xMove = x;yMove = y;int dx = xMove – xDown;int dy = yMove – yDown;/*** 判断是否是从右到左的滑动*/if (xMove < xDown && Math.abs(dx) > touchSlop && Math.abs(dy) < touchSlop){// Log.e(TAG, "touchslop = " + touchSlop + " , dx = " + dx +// " , dy = " + dy);isSliding = true;}break;}return super.dispatchTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent ev){int action = ev.getAction();/** * 如果是从右到左的滑动才相应 */if (isSliding){switch (action){case MotionEvent.ACTION_MOVE:int[] location = new int[2];// 获得当前item的位置x与ymCurrentView.getLocationOnScreen(location);// 设置popupWindow的动画mPopupWindow.setAnimationStyle(R.style.popwindow_delete_btn_anim_style);mPopupWindow.update();mPopupWindow.showAtLocation(mCurrentView, Gravity.LEFT | Gravity.TOP,location[0] + mCurrentView.getWidth(), location[1] + mCurrentView.getHeight() / 2- mPopupWindowHeight / 2);// 设置删除按钮的回调mDelBtn.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v){if (mListener != null){mListener.clickHappend(mCurrentViewPos);mPopupWindow.dismiss();}}});// Log.e(TAG, "mPopupWindow.getHeight()=" + mPopupWindowHeight);break;case MotionEvent.ACTION_UP:isSliding = false;}// 相应滑动期间屏幕itemClick事件,避免发生冲突return true;}return super.onTouchEvent(ev);}/** * 隐藏popupWindow */private void dismissPopWindow(){if (mPopupWindow != null && mPopupWindow.isShowing()){mPopupWindow.dismiss();}}public void setDelButtonClickListener(DelButtonClickListener listener){mListener = listener;}interface DelButtonClickListener{public void clickHappend(int position);}}代码注释写得很详细,简单说一下,在dispatchTouchEvent中设置当前是否响应用户滑动,然后在onTouchEvent中判断是否响应,如果响应则popupWindow以动画的形式展示出来。当然屏幕上如果存在PopupWindow则屏幕ListView的滚动与Item的点击,以及从右到左滑动时屏幕Item的click事件。生气是拿别人做错的事来惩罚自己

ListView滑动删除 ,仿腾讯QQ

相关文章:

你感兴趣的文章:

标签云: