首页 > 代码库 > Scroller应用:ListView滑动删除
Scroller应用:ListView滑动删除
1、设计思路
在Scroller的应用--滑屏实现中使用Scroller实现滑屏效果,这里使用Scroller与ListView实现类似QQ滑动,然后点击删除功能,设计思路是Item使用Scroller实现滑动,ListView根据触摸判断是横向滑动还是竖直滑动,关于点击事件处理思路:对于View的onClick事件跟平常一样,里面针对OnItemClick做了处理,判断触摸距离来判断,如果小于5的话,在Item的onTouchEvent方法中的MotionEvent.ACTION_UP里面返回false,这样ListView里面的dispatchTouchEvent的super.dispatchTouchEvent(event)就会返回false,根据x,y获取当前position以及点击的view,调用super.performItemClick(view, position, view.getId());来告诉ListView出发onItemClick事件。
2、Item的代码
package com.jwzhangjie.scrollview; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.LinearLayout; import android.widget.Scroller; public class ListItemDelete extends LinearLayout { private Scroller mScroller;// 滑动控制 private float mLastMotionX;// 记住上次触摸屏的位置 private int deltaX; private int back_width; private float downX; public ListItemDelete(Context context) { this(context, null); } public ListItemDelete(Context context, AttributeSet attrs) { super(context, attrs); init(context); } private void init(Context context) { mScroller = new Scroller(context); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) {// 会更新Scroller中的当前x,y位置 scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int count = getChildCount(); for (int i = 0; i < count; i++) { measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec); if (i == 1) { back_width = getChildAt(i).getMeasuredWidth(); } } } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); float x = event.getX(); switch (action) { case MotionEvent.ACTION_DOWN: Log.e("test", "item ACTION_DOWN"); mLastMotionX = x; downX = x; break; case MotionEvent.ACTION_MOVE: Log.e("test", back_width + " item ACTION_MOVE " + getScrollX()); deltaX = (int) (mLastMotionX - x); mLastMotionX = x; int scrollx = getScrollX() + deltaX; if (scrollx > 0 && scrollx < back_width) { scrollBy(deltaX, 0); } else if (scrollx > back_width) { scrollTo(back_width, 0); } else if (scrollx < 0) { scrollTo(0, 0); } break; case MotionEvent.ACTION_UP: Log.e("test", "item ACTION_UP"); int scroll = getScrollX(); if (scroll > back_width / 2) { scrollTo(back_width, 0); } else { scrollTo(0, 0); } if (Math.abs(x - downX) < 5) {// 这里根据点击距离来判断是否是itemClick return false; } break; case MotionEvent.ACTION_CANCEL: scrollTo(0, 0); break; } return true; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int margeLeft = 0; int size = getChildCount(); for (int i = 0; i < size; i++) { View view = getChildAt(i); if (view.getVisibility() != View.GONE) { int childWidth = view.getMeasuredWidth(); // 将内部子孩子横排排列 view.layout(margeLeft, 0, margeLeft + childWidth, view.getMeasuredHeight()); margeLeft += childWidth; } } } }
3、ListView的代码
package com.jwzhangjie.scrollview; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.widget.ListView; public class ScrollListviewDelete extends ListView { private float minDis = 10; private float mLastMotionX;// 记住上次X触摸屏的位置 private float mLastMotionY;// 记住上次Y触摸屏的位置 private boolean isLock = false; public ScrollListviewDelete(Context context, AttributeSet attrs) { super(context, attrs); } /** * 如果一个ViewGroup的onInterceptTouchEvent()方法返回true,说明Touch事件被截获, * 子View不再接收到Touch事件,而是转向本ViewGroup的 * onTouchEvent()方法处理。从Down开始,之后的Move,Up都会直接在onTouchEvent()方法中处理。 * 先前还在处理touch event的child view将会接收到一个 ACTION_CANCEL。 * 如果onInterceptTouchEvent()返回false,则事件会交给child view处理。 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (!isIntercept(ev)) { return false; } return super.onInterceptTouchEvent(ev); } @Override public boolean dispatchTouchEvent(MotionEvent event) { boolean dte = super.dispatchTouchEvent(event); if (MotionEvent.ACTION_UP == event.getAction() && !dte) {//onItemClick int position = pointToPosition((int)event.getX(), (int)event.getY()); View view = getChildAt(position); super.performItemClick(view, position, view.getId()); } return dte; } @Override // 处理点击事件,如果是手势的事件则不作点击事件 普通View public boolean performClick() { return super.performClick(); } @Override // 处理点击事件,如果是手势的事件则不作点击事件 ListView public boolean performItemClick(View view, int position, long id) { return super.performItemClick(view, position, id); } /** * 检测是ListView滑动还是item滑动 isLock 一旦判读是item滑动,则在up之前都是返回false */ private boolean isIntercept(MotionEvent ev) { float x = ev.getX(); float y = ev.getY(); int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: Log.e("test", "isIntercept ACTION_DOWN "+isLock); mLastMotionX = x; mLastMotionY = y; break; case MotionEvent.ACTION_MOVE: Log.e("test", "isIntercept ACTION_MOVE "+isLock); if (!isLock) { float deltaX = Math.abs(mLastMotionX - x); float deltay = Math.abs(mLastMotionY - y); mLastMotionX = x; mLastMotionY = y; if (deltaX > deltay && deltaX > minDis) { isLock = true; return false; } } else { return false; } break; case MotionEvent.ACTION_UP: Log.e("test", "isIntercept ACTION_UP "+isLock); isLock = false; break; case MotionEvent.ACTION_CANCEL: Log.e("test", "isIntercept ACTION_CANCEL "+isLock); isLock = false; break; } return true; } }
4、Activity代码
package com.jwzhangjie.scrollview;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListView;
public class ScrollListviewDelete extends ListView {
private float minDis = 10;
private float mLastMotionX;// 记住上次X触摸屏的位置
private float mLastMotionY;// 记住上次Y触摸屏的位置
private boolean isLock = false;
public ScrollListviewDelete(Context context, AttributeSet attrs) {
super(context, attrs);
}
/**
* 如果一个ViewGroup的onInterceptTouchEvent()方法返回true,说明Touch事件被截获,
* 子View不再接收到Touch事件,而是转向本ViewGroup的
* onTouchEvent()方法处理。从Down开始,之后的Move,Up都会直接在onTouchEvent()方法中处理。
* 先前还在处理touch event的child view将会接收到一个 ACTION_CANCEL。
* 如果onInterceptTouchEvent()返回false,则事件会交给child view处理。
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (!isIntercept(ev)) {
return false;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
boolean dte = super.dispatchTouchEvent(event);
if (MotionEvent.ACTION_UP == event.getAction() && !dte) {//onItemClick
int position = pointToPosition((int)event.getX(), (int)event.getY());
View view = getChildAt(position);
super.performItemClick(view, position, view.getId());
}
return dte;
}
@Override
// 处理点击事件,如果是手势的事件则不作点击事件 普通View
public boolean performClick() {
return super.performClick();
}
@Override
// 处理点击事件,如果是手势的事件则不作点击事件 ListView
public boolean performItemClick(View view, int position, long id) {
return super.performItemClick(view, position, id);
}
/**
* 检测是ListView滑动还是item滑动 isLock 一旦判读是item滑动,则在up之前都是返回false
*/
private boolean isIntercept(MotionEvent ev) {
float x = ev.getX();
float y = ev.getY();
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
Log.e("test", "isIntercept ACTION_DOWN "+isLock);
mLastMotionX = x;
mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
Log.e("test", "isIntercept ACTION_MOVE "+isLock);
if (!isLock) {
float deltaX = Math.abs(mLastMotionX - x);
float deltay = Math.abs(mLastMotionY - y);
mLastMotionX = x;
mLastMotionY = y;
if (deltaX > deltay && deltaX > minDis) {
isLock = true;
return false;
}
} else {
return false;
}
break;
case MotionEvent.ACTION_UP:
Log.e("test", "isIntercept ACTION_UP "+isLock);
isLock = false;
break;
case MotionEvent.ACTION_CANCEL:
Log.e("test", "isIntercept ACTION_CANCEL "+isLock);
isLock = false;
break;
}
return true;
}
}
5、XML代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.jwzhangjie.scrollview.ScrollListviewDelete
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<com.jwzhangjie.scrollview.ListItemDelete xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<LinearLayout
android:id="@+id/front"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_item_list_8"
android:gravity="center"
android:orientation="horizontal" >
<TextView
android:id="@+id/itemData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试数据" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal" >
<Button
android:id="@+id/btnNao"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@drawable/bg_item_list_4"
android:text="闹铃" />
<Button
android:id="@+id/btnDelete"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@drawable/bg_item_list_5"
android:text="删除" />
</LinearLayout>
</com.jwzhangjie.scrollview.ListItemDelete>
6、界面效果
代码地址:https://github.com/jwzhangjie/-ScrollerDelete
Scroller应用:ListView滑动删除
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。