Android 仿QQlistview侧滑删除
Posted BIGPiePieTree
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 仿QQlistview侧滑删除相关的知识,希望对你有一定的参考价值。
最近在项目中要实现listview的item能够侧滑显示按钮,然后点击删除对应的那一条数据。记得好像github上有一个开源的能实现这种效果,但是想想好像也不会太难,而且之前有很认真的了解过事件分发机制,大概整理整理思路 ,就动手自己写了一个。不过好像有些地方实现的效果不是太理想,以后还会有很大的改进余地。
我们来看看效果
在动手实现之前我们需要了解一下事件分发机制 以前在这里了解的Android事件分发机制完全解析,带你从源码的角度彻底理解(上),这里有个图一目了然
做个比喻,就像给公司老总提交涨工资,先给组长传达吧,组长看你工作努力,统一给你往上报,好嘛给部长了,部长觉得你能力不太行,然后就把申请书扣押下来自己处理,不传递给上级,然后通过组长告诉你,没戏!
既然对大概的情况了解我们就话不多说,我们来一步一步分解。
我们定义 一个DeleteListView 继承自ListView
并定义我们等下需要用到了一些变量
private Scroller scroller; //滑动类
private int minDelta; //最小滑动距离
private int mDownX; //手指按下时的坐标
private int mDownY;
private int itemPosition; // 手指按下时所对应的item位置
private boolean isSlide; //是否item可以滑动
private static int S_VELOCITY = 1200;
private VelocityTracker velocityTracker; //速度跟踪器
private View itemview; //得到滑动的item
private String TAG = "XIONG";
//监听滑动
private SubViewClickListener subViewClickListener;
//滑动方向
int removeDirection;
private final int TO_LEFT = 0;
private final int TO_RITHG = 1;
//删除按钮的 宽度
int d_width = 0;
后面都有注释,我就不一一解释是什么意思了,等下我们用到的时候你就知道了。
重点是这两个方法我们需要重写
一是 dispatchTouchEvent() 我们来看一下
@Override
public boolean dispatchTouchEvent(MotionEvent event)
switch (event.getAction())
case MotionEvent.ACTION_DOWN:
isSlide = false;
addVelocityTracker(event);
//如果listview滑动还没有结束的时候 直接返回让listview处理滑动事件
if (!scroller.isFinished())
return super.dispatchTouchEvent(event);
mDownX = (int) event.getX();
mDownY = (int) event.getY();
//通过点击的坐标得到点击的子item的位置
itemPosition = pointToPosition(mDownX, mDownY);
Log.d(TAG, "touch position" + itemPosition);
if (itemPosition == AdapterView.INVALID_POSITION)
return super.dispatchTouchEvent(event);
itemview = getChildAt(itemPosition - getFirstVisiblePosition());
itemview.findViewById(R.id.deledt_item).setOnClickListener(new OnClickListener()
@Override
public void onClick(View v)
itemview.scrollTo(0, 0);
subViewClickListener.subClick(itemPosition);
);
break;
case MotionEvent.ACTION_MOVE:
float tX = Math.abs(event.getX() - mDownX);
float tY = Math.abs(event.getY() - mDownY); // 当x方向偏移量大于y方向并且都大于最小偏移时
if (((tX > minDelta) && (tY < minDelta) && tX > tY) || getVelocity() > S_VELOCITY)
isSlide = true;
break;
case MotionEvent.ACTION_UP:
clearVelocityTracker();
break;
return super.dispatchTouchEvent(event);
在这里 我们在滑动listview的时候 先把event这个动作传给速度跟踪器,在这里我们要通过scroller来知道是不是listview还在滑动,如果还在滑动的话
return super.dispatchTouchEvent(event);
把它交给listview自己处理滑动事件,下面也是。然后我们通过按下的坐标获取对应的item并且给子view添加点击事件。
另外一个重写的方法是onTouchEvent()方法
@Override
public boolean onTouchEvent(MotionEvent ev)
if (isSlide && itemPosition != AdapterView.INVALID_POSITION)
// 拦截监听事件
requestDisallowInterceptTouchEvent(true);
addVelocityTracker(ev);
int x = (int) ev.getX();
switch (ev.getAction())
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
MotionEvent cancelEvent = MotionEvent.obtain(ev);
cancelEvent.setAction(MotionEvent.ACTION_CANCEL |
(ev.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
onTouchEvent(cancelEvent);
int deltaX = mDownX - x;
mDownX = x;
// 向左滑动的时候 , deltax>0 但是如果滑动的速度比较快,会造成删除部分太过向左
// 所以 当deltax超出范围时,控制到能达到的最大距离
if (deltaX > 0)
if (Math.abs(itemview.getScrollX()) < d_width - 40)
if (itemview.getScrollX() + deltaX > 400)
deltaX = 400 - itemview.getScrollX();
removeDirection = TO_LEFT;
itemview.scrollBy(deltaX, 0);
else
//向右滑动回复未滑动状态时
if (itemview.getScrollX() > 0)
removeDirection = TO_RITHG;
itemview.scrollBy(deltaX, 0);
return true;
case MotionEvent.ACTION_UP:
// 当手指滑动距离短但是速度比较快时 ,判断向左还是向右
int v = getVelocity();
if (v > S_VELOCITY)
scrollToLeft();
else if (v < -S_VELOCITY)
scrollToRight(itemview);
else
scrollByDistanceX();
return super.onTouchEvent(ev);
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.xiong.listviewdelete.DeleteListView
android:id="@+id/delete_listview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.example.xiong.listviewdelete.DeleteListView>
</RelativeLayout>
deleteListView = (DeleteListView) findViewById(R.id.delete_listview);
for (int i = 0; i < 20; i++)
dataSourceList.add("第" + i + "个");
baseAdapter = new ArrayAdapter<String>(this, R.layout.item, R.id.list_item, dataSourceList);
deleteListView.setAdapter(baseAdapter);
deleteListView.setSubViewClickListener(new DeleteListView.SubViewClickListener()
@Override
public void subClick(int position)
);
以上是关于Android 仿QQlistview侧滑删除的主要内容,如果未能解决你的问题,请参考以下文章
Android使用DrawerLayout仿qq6.6版本侧滑效果
Android使用DrawerLayout仿qq6.6版本侧滑效果