在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事件。
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; } } } }
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; } }
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; } }