1. 程式人生 > >由View點選和長按同時存在導致衝突看View的事件分發

由View點選和長按同時存在導致衝突看View的事件分發

            如果一個View同時設定了點選監聽setOnclickListener和長按setOnLongClickListener時,這時如果你想長按的時候彈出一個對話方塊,點選的時候跳轉到另一個頁面的時候,如下:

		button.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				//跳轉到另一個頁面
			}
		});
		button.setOnLongClickListener(new OnLongClickListener() {
			
			@Override
			public boolean onLongClick(View v) {
				//彈出對話方塊
				return false;
			}
		});
那這時如果你想長按彈出對話方塊的時候,會出現這樣的一個情況,就是當你長按的時候觸發OnLongClickListener,毋庸置疑會彈出對話方塊。但是當你擡起手指的時候你會發現跳轉到了另一個頁面,也就是觸發了點選監聽OnClickListener,那這樣的衝突如何解決和為什麼會出現這樣的衝突呢?這個要從Android系統中的View事件分發著手。

        在Android系統中,View的事件分發涉及到3個方法啊,事件分發的流程為:整個View的事件轉發流程是:dispatchTouchEvent->onInterceptTouchEvent->onTouchEvent,如果你對這個瞭解的話,那接著我們將由此引出2個問題:

1.View.setOnTouchListener和onTouchEvent的關係?

1)在dispatchTouchEvent中會進行OnTouchListener的判斷,如果OnTouchListener不為null且返回true(此時dispatchTouchEvent也將返回true),則表示事件被消費,onTouchEvent不會被執行;否則執行onTouchEvent

2)OnLongClickListener和OnClickListener在view的onTouchEvent中判斷,setOnTouchListener返回true或dispatchTouchEvent返回true,點選和長按都不會得到執行

2.如何解決onClickListener和onLongClickListener同時存在的衝突

1)在onTouchEvent中,長按監聽事件OnLongClickListener是通過down判斷的,當手指按下的時候,有一個500毫秒的時間來判斷,如果超過了500毫秒則視為長按事件。而點選事件OnClickListener是通過up判斷的

由此可以看出,OnLongClickListener和OnClickListener事件都是在onTouchEvent中判斷的,是優於OnLongClickListener事件優於OnClickListener執行的,所以也就解釋了上面的示例當我們手指按下的時候會彈出對話方塊,而如果沒有任何處理的話手指擡起會跳轉到另一個頁面。

那麼此時我們可以直接將OnLongClickListener的返回值設定為true,那麼這時長按的時候就會遮蔽點選事件,點選的時候也會執行所需要的操作。