1. 程式人生 > >Android開發:在onTouchEvent中處理任意時間的長按事件

Android開發:在onTouchEvent中處理任意時間的長按事件

Android提供了GestureDetector類來處理一些常用的手勢操作,比如說 onLongPress,onFling 等。但這裡不使用GestureDetector,而是直接在自定義View重寫的onTouchEvent中進行處理。

欲實現的效果是:當手機按住螢幕時,如果在指定的時間內沒有移動(如500毫秒),那麼進入長按模式,此時手指在螢幕上移動都算作長按模式。如果手機按住螢幕就立馬移動,那麼就算作移動模式。

MotionEvent 類提供了記錄當前座標的函式(getX(),getY())和當前事件產生的時間的函式(getEventTime())以及按下時間(getDowntime())。MotionEvent同時也提供了當前的操作型別,按下(ACTION_DOWN)、 移動 (ACTION_MOVE)、彈起 (ACTION_UP)。有了這些引數,我們便可以輕易的實現想要的效果了。

大概思路如下:在按下時記錄x,y座標以及按下時間,當第一次移動的時候獲取移動的時間,如果大於指定的長按時間,那麼進入長按模式,否則就是普通的移動模式。很容易,在模擬器裡面實現了這個效果,但是當在真機裡面執行時,卻無法實現這樣的效果。原來模擬器點選的時候能夠保證在不移動滑鼠的情況下不觸發ACTION_MOVE,但是真機卻很敏感,幾乎在ACTION_DOWN後的幾毫秒之後就立馬不停的ACTION_MOVE了。想了一下,其實只要稍微變通下變可以在真機上也實現相同的效果了。那就是判斷ACTION_MOVE後的座標和ACTION_DOWN的座標的偏移值是否小於我們指定的偏移畫素,如果在指定值內,那麼認為沒有移動。於是有了如下這個函式。

/**
	 * * 判斷是否有長按動作發生 * @param lastX 按下時X座標 * @param lastY 按下時Y座標 *
	 * 
	 * @param thisX
	 *            移動時X座標 *
	 * @param thisY
	 *            移動時Y座標 *
	 * @param lastDownTime
	 *            按下時間 *
	 * @param thisEventTime
	 *            移動時間 *
	 * @param longPressTime
	 *            判斷長按時間的閥值
	 */
	static boolean isLongPressed(float lastX, float lastY, float thisX,
			float thisY, long lastDownTime, long thisEventTime,
			long longPressTime) {
		float offsetX = Math.abs(thisX - lastX);
		float offsetY = Math.abs(thisY - lastY);
		long intervalTime = thisEventTime - lastDownTime;
		if (offsetX <= 10 && offsetY <= 10 && intervalTime >= longPressTime) {
			return true;
		}
		return false;
	}

在ACTION_DOWN的時候,記錄下lastX,lastY和lastDownTime,在ACTION_MOVE的時候判斷當前是否為長按模式(類標誌變數的方式),如果不是,那麼獲取當前的thisX,thisY和thisEventTime呼叫函式進行判斷。最後別忘記在ACTION_UP裡將長按標誌值為FALSE。ACTION_DOWN裡面這樣處理:

//檢測是否長按,在非長按時檢測 
	if(!mIsLongPressed){ 
		mIsLongPressed = isLongPressed(mLastMotionX, mLastMotionY, x, y, lastDownTime,eventTime,500); 
		} 
	if(mIsLongPressed){  
		//長按模式所做的事 
		}else{  
			//移動模式所做的事
	}
}