在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;
}
}
