Android自定義長按事件

比如當希望長按的時間更長一點的時候。這時候就需要自己來定義這個長按事件了。下面是去年我寫代碼的時候,自定義長按事件的方式:
package chroya.fun;

import android.content.Context;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

public class LongPressView1 extends View{
	private int mLastMotionX, mLastMotionY;
	//是否移動了
	private boolean isMoved;
	//是否釋放了
	private boolean isReleased;
	//計數器,防止多次點擊導致最後一次形成longpress的時間變短
	private int mCounter;
	//長按的runnable
	private Runnable mLongPressRunnable;
	//移動的閾值
	private static final int TOUCH_SLOP = 20;

	public LongPressView1(Context context) {
		super(context);
		mLongPressRunnable = new Runnable() {
			
			@Override
			public void run() {
				mCounter--;
				//計數器大於0,說明當前執行的Runnable不是最後一次down產生的。
				if(mCounter>0 || isReleased || isMoved) return;
				performLongClick();
			}
		};
	}

	public boolean dispatchTouchEvent(MotionEvent event) {
		int x = (int) event.getX();
		int y = (int) event.getY();
		
		switch(event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			mLastMotionX = x;
			mLastMotionY = y;
			mCounter++;
			isReleased = false;
			isMoved = false;
			postDelayed(mLongPressRunnable, ViewConfiguration.getLongPressTimeout());
			break;
		case MotionEvent.ACTION_MOVE:
			if(isMoved) break;
			if(Math.abs(mLastMotionX-x) > TOUCH_SLOP 
					|| Math.abs(mLastMotionY-y) > TOUCH_SLOP) {
				//移動超過閾值,則表示移動了
				isMoved = true;
			}
			break;
		case MotionEvent.ACTION_UP:
			//釋放了
			isReleased = true;
			break;
		}
		return true;
	}
}


代碼裏註釋的比較清楚。主要思路是在down的時候,讓一個Runnable一段時間後執行,如果時間到了,沒有移動超過定義的閾值,也沒有釋放,則觸發長按事件。在真實環境中,當長按觸發之後,還需要將後來的move和up事件屏蔽掉。此處是示例,就略去了。

package chroya.fun;

import android.content.Context;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;

public class LongPressView2 extends View{
	private int mLastMotionX, mLastMotionY;
	//是否移動了
	private boolean isMoved;
	//長按的runnable
	private Runnable mLongPressRunnable;
	//移動的閾值
	private static final int TOUCH_SLOP = 20;

	public LongPressView2(Context context) {
		super(context);
		mLongPressRunnable = new Runnable() {
			
			@Override
			public void run() {				
				performLongClick();
			}
		};
	}

	public boolean dispatchTouchEvent(MotionEvent event) {
		int x = (int) event.getX();
		int y = (int) event.getY();
		
		switch(event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			mLastMotionX = x;
			mLastMotionY = y;
			isMoved = false;
			postDelayed(mLongPressRunnable, ViewConfiguration.getLongPressTimeout());
			break;
		case MotionEvent.ACTION_MOVE:
			if(isMoved) break;
			if(Math.abs(mLastMotionX-x) > TOUCH_SLOP 
					|| Math.abs(mLastMotionY-y) > TOUCH_SLOP) {
				//移動超過閾值,則表示移動了
				isMoved = true;
				removeCallbacks(mLongPressRunnable);
			}
			break;
		case MotionEvent.ACTION_UP:
			//釋放了
			removeCallbacks(mLongPressRunnable);
			break;
		}
		return true;
	}
}


思路跟第一種差不多,不過,在移動超過閾值和釋放之後,會將Runnable從事件隊列中remove掉,長按事件也就不會再觸發了。源碼中實現長按的原理也基本如此。

工程見附件。

Funny.zip (53.6 KB)下載次數: 646

http://chroya.iteye.com/blog/804706

 

 Activity調用。

public class MainActivity extends Activity {
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        View mLongPressView = new LongPressView(this);
        mLongPressView.setOnLongClickListener(new OnLongClickListener() {
			@Override
			public boolean onLongClick(View v) {

				Toast.makeText(MainActivity.this,
						"I got a long press!", Toast.LENGTH_SHORT).show();
				return false;
			}
		});
        setContentView(mLongPressView);
    }
}

 

LongPressEventDemo.rar (14.4 KB)下載次數: 7

http://elingwange.iteye.com/blog/1666741

 

http://blog.csdn.net/eoeandroida/article/details/8308877http://www.open-open.com/lib/view/open1362710410109.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章