程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Scroller應用:ListView滑動刪除

Scroller應用:ListView滑動刪除

編輯:C++入門知識

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代碼

 

 

        
    

    

6、界面效果

/

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved