原文:ListView滑动删除 ,仿腾讯QQ(鸿洋_)

文章实现的功能是:在ListView的Item上从右向左滑时,出现删除按钮,点击删除按钮把Item删除。

看过文章后,感觉没有必要把dispatchTouchEvent()和onTouchEvent()两个方法都重写,只要重写onTouchEvent就好了。于是对代码作了一些调整:

public class MyListView extends ListView {
private static final String TAG = "MyListView";
private int mTouchSlop;
private int mXDown;
private int mYDown;
private int mCurrentPosition;
private View mCurrentView;
private PopupWindow mPopupWindow;
private LayoutInflater mInflater;
private boolean isSliding = false;
// 为删除按钮提供一个回调接口
private DelButtonClickListener mListener;
private Button mDelBtn;
private int mPopupWindowHeight;
private int mPopupWindowWidth; public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
mInflater = LayoutInflater.from(context);
mTouchSlop = 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);
// 如果需要通过点击PopupWindow之外的地方使其消失,则需要setFocusable(true).
mPopupWindow.setFocusable(true);
// Android 6.0以前的版本需要setBackgroundDrawable(),
// 才能实现通过点击PopupWindow之外的地方使其消失的功能。
mPopupWindow.setBackgroundDrawable(new ColorDrawable(0));
// 先调用下measure,否则拿不到宽和高
mPopupWindow.getContentView().measure(0, 0);
mPopupWindowHeight = mPopupWindow.getContentView().getMeasuredHeight();
mPopupWindowWidth = mPopupWindow.getContentView().getMeasuredWidth();
} @Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
int x = (int) ev.getX();
int y = (int) ev.getY(); switch (action){
case MotionEvent.ACTION_DOWN:
isSliding = false;
mXDown = x;
mYDown = y;
mCurrentPosition = pointToPosition(mXDown, mYDown);
View view = getChildAt(mCurrentPosition - getFirstVisiblePosition());
mCurrentView = view;
break;
case MotionEvent.ACTION_MOVE:
int dx = x - mXDown;
int dy = y - mYDown; Log.d(TAG, "mTouchSlop = " + mTouchSlop + ", dx = " + dx + ", dy = " + dy); if(mXDown > x && Math.abs(dx) > mTouchSlop && Math.abs(dy) < mTouchSlop){
Log.d(TAG, "isSliding");
isSliding = true;
int[] location = new int[2];
mCurrentView.getLocationOnScreen(location);
mPopupWindow.setAnimationStyle(R.style.popwindow_delete_btn_anim_style);
mPopupWindow.update();
Log.d(TAG, "Height: " + mCurrentView.getHeight() + "," + mPopupWindow.getHeight());
mPopupWindow.showAtLocation(mCurrentView, Gravity.NO_GRAVITY,
location[0] + mCurrentView.getWidth(),
location[1] + mCurrentView.getHeight() / 2 - mPopupWindowHeight / 2);
mDelBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mListener.clickHappend(mCurrentPosition);
mPopupWindow.dismiss();
}
});
}
case MotionEvent.ACTION_UP:
// isSliding 如果这里恢复为false,则后面会执行super.onTouchEvent事件,
// 而AbsListView的onTouchEvent调用了onTouchUp方法,在onTouchUp方法中有可能执行
// performClick.run() --> performItemClick() --> super.performItemClick
// --> mOnItemClickListener.onItemClick,这样最终触发Item的点击。
// 因此此处依旧保持isSliding为true的状态,而在ACTION_DOWN事件中恢复isSliding为false,
// 毕竟每个事件都以ACTION_DOWN开始。
//isSliding = false;
} if(isSliding){
return true;
} return super.onTouchEvent(ev);
} public void setDelButtonClickListener(DelButtonClickListener listener){
mListener = listener;
} interface DelButtonClickListener{
public void clickHappend(int position);
}
}

MyListView.java

通过这个例子学习到:

1、ListView的Item点击事件的触发过程:

自定义ListView的onTouchEvent()  ---调用super.onTouchEvent()---> AbsListView.onTouchEvent() ---MotionEvent.ACTION_UP---> AbsListView.onTouchUp()

---(有可能)调用performClick.run()---> AbsListView.PerformClick.run() ---调用performItemClick()---> AbsListView.performItemClick()

---(有可能)调用super.performItemClick()---> AdapterView.performItemClick() ---mOnItemClickListener.onItemClick---> OnItemClickListener.onItemClick()

也就是Item的点击事件是在MotionEvent.ACTION_UP事件完成的,这样在自定义ListView的onTouchEvent()中,对MotionEvent.ACTION_UP直接return true消费掉事件,而不要调用super.onTouchEvent。这样就避免了删除按钮与Item点击事件的冲突。

2、PopupWindow--通过点击PopupWindow之外的地方使其消失

a、需要调用setFocusable()方法(PopupWindow中showAtLocation() --> createPopupLayoutParams() --> computeFlags() --> 设置FLAG_NOT_FOCUSABLE);

b、Android 6.0以前的版本需要setBackgroundDrawable()(具体原因见:PopupWindow的使用)。

ListView + PopupWindow实现滑动删除的更多相关文章

  1. Android 用HorizontalScrollView实现ListView的Item滑动删除 ,滑动错乱 冲突

    用HorizontalScrollView实现类似微信的滑动删除 测试于:Android2.2+ 对于Android来说按键操作已经在减少,越来越多的手势操作层出不穷,今天介绍一款LIstView的I ...

  2. Android 高级UI设计笔记03:使用ListView实现左右滑动删除Item

    1. 这里就是实现一个很简单的功能,使用ListView实现左右滑动删除Item: (1)当我们在ListView的某个Item,向左滑动显示一个删除按钮,用户点击按钮,即可以删除该项item,并且有 ...

  3. android中listview的item滑动删除效果(已解决listview点击问题)

    领导看到iphone上tableview有个滑动删除的效果,要求在android上也实现,搜了下资料,实现起来比较简单,可弄到后面,居然不能点击了,把一篇文章中的代码修改了一下,捣鼓了一番,搞定,下面 ...

  4. Android 使用NineOldAndroids实现绚丽的ListView左右滑动删除Item效果

    本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/18311877) 今天还是给大家带来自定义控件的编写,自定义一个Lis ...

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

    今天研究了一下android里面的手势,结合昨天学习的自定义View,做了一个自定义的listview,继承自listView,添加了条目的滑动手势操作,滑动后出现一个删除按钮,点击删除按钮,触发一个 ...

  6. android滑动删除的多种实现方式(一)

    个人习惯,先上图 同事是个妹子(这点很重要),写滑动删除动能的时候用到了SwipeLayout,然后悲催的是,滑动时间被拦截了,解决方法先不提,在(一)中先讲解SwipeLayout下载listvie ...

  7. ListView滑动删除效果实现

    通过继承ListView然后结合PopupWindow实现 首先是布局文件: delete_btn.xml:这里只需要一个Button <?xml version="1.0" ...

  8. 【转】Android 实现ListView的滑动删除效果

    http://www.cnblogs.com/weixiao870428/p/3524055.html http://download.csdn.net/download/love_javc_you/ ...

  9. 【转】Android 使用Scroller实现绚丽的ListView左右滑动删除Item效果

    原文网址:http://blog.csdn.net/xiaanming/article/details/17539199 转帖请注明本文出自xiaanming的博客(http://blog.csdn. ...

随机推荐

  1. 流媒体(音频 AudioStreamer)

    AudioStreamer 在github可以搜索到, 专门播放流媒体(音频)

  2. php写入txt换行符

    1.问题 写入txt文件想换行,老是直接输出了\r\n. 2.解决 要用双引号对\r\n进行解释,否则php会直接当字符输出. 3.例子 要求:往test.txt文本每一行后面加abc $a=file ...

  3. 剑指Offer 二叉树中和为某一值的路径(dfs)

    题目描述 输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径.路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径.     思路: 递归,然后深搜,因为题目定义的, ...

  4. OpenCV成长之路(7):图像滤波

    滤波实际上是信号处理里的一个概念,而图像本身也可以看成是一个二维的信号.其中像素点灰度值的高低代表信号的强弱. 高频:图像中灰度变化剧烈的点. 低频:图像中平坦的,灰度变化不大的点. 根据图像的高频与 ...

  5. 9.3---魔术索引(CC150)

    魔术索引1:此外下一次应该看看课本上的方法. public boolean findMagicIndex(int[] A, int n){ for(int i = 0; i < A.length ...

  6. Redis常用数据类型介绍、使用场景及其操作命令

    Redis常用数据类型介绍.使用场景及其操作命令 本文章同时也在cpper.info发布. Redis目前支持5种数据类型,分别是: 1.String(字符串) 2.List(列表) 3.Hash(字 ...

  7. memcache的带图形界面监控工具memcachephp

    memcache也有一款图形界面的监控工具(memcachephp),可以通过这个工具查看到局域网内所有部署memcache机器或者端口的memcache的运行情况,对我们监控memcache的缓存命 ...

  8. POJ 1308

    http://poj.org/problem?id=1308 题意:判断这是不是一棵树. 思路:这个题还是有部分坑点的.首先空树也是一棵树,还有森林不是树. 关于森林的判断我是利用并查集把每一个点压缩 ...

  9. struts2 复杂参数封装

    1.1.1    Struts2中封装复杂类型的数据: 封装到List集合: 页面: 商品名称:<input type="text" name="products[ ...

  10. linux shell脚本通过参数名传递参数值

    平常在写shell脚本都是用$1,$2....这种方式来接收参数,然而这种接收参数的方式不但容易忘记且不易于理解和维护.Linux常用的命令都可指定参数名和参数值,然而我们怎样才能给自己的shell脚 ...