日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Android觸摸事件與點(diǎn)擊事件的區(qū)別

針對(duì)屏幕上的一個(gè)View控件,Android如何區(qū)分應(yīng)當(dāng)觸發(fā)onTouchEvent,還是onClick,亦或是onLongClick事件?

公司主營(yíng)業(yè)務(wù):成都網(wǎng)站制作、做網(wǎng)站、移動(dòng)網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。成都創(chuàng)新互聯(lián)公司是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來驚喜。成都創(chuàng)新互聯(lián)公司推出鼓樓免費(fèi)做網(wǎng)站回饋大家。

在Android中,一次用戶操作可以被不同的View按次序分別處理,并將完全響應(yīng)了用戶一次UI操作稱之為消費(fèi)了該事件(consume),那么Android是按什么次序?qū)⑹录鬟f的呢?又在什么情況下判定為消費(fèi)了該事件?

搞清楚這些問題對(duì)于編寫出能正確響應(yīng)UI操作的代碼是很重要的,尤其當(dāng)屏幕上的不同View需要針對(duì)此次UI操作做出各種不同響應(yīng)的時(shí)候更是如此,一個(gè)典型例子就是用戶在桌面上放置了一個(gè)Widget,那么當(dāng)用戶針對(duì)widget做各種操作時(shí),桌面本身有的時(shí)候要對(duì)用戶的操作做出響應(yīng),有時(shí)忽略。只有搞清楚事件觸發(fā)和傳遞的機(jī)制才有可能保證在界面布局非常復(fù)雜的情況下,UI控件仍然能正確響應(yīng)用戶操作。

1.  onTouchEvent

onTouchEvent中要處理的最常用的3個(gè)事件就是:ACTION_DOWN、ACTION_MOVE、ACTION_UP。

這三個(gè)事件標(biāo)識(shí)出了最基本的用戶觸摸屏幕的操作,含義也很清楚。雖然大家天天都在用它們,但是有一點(diǎn)請(qǐng)留意,ACTION_DOWN事件作為起始事件,它的重要性是要超過ACTION_MOVE和ACTION_UP的,如果發(fā)生了ACTION_MOVE或者ACTION_UP,那么一定曾經(jīng)發(fā)生了ACTION_DOWN。

從Android的源代碼中能看到基于這種不同重要性的理解而實(shí)現(xiàn)的一些交互機(jī)制,SDK中也有明確的提及,例如在ViewGroup的onInterceptTouchEvent方法中,如果在ACTION_DOWN事件中返回了true,那么后續(xù)的事件將直接發(fā)給onTouchEvent,而不是繼續(xù)發(fā)給onInterceptTouchEvent。

2.  onClick、onLongClick與onTouchEvent

曾經(jīng)看過一篇帖子提到,如果在View中處理了onTouchEvent,那么就不用再處理onClick了,因?yàn)锳ndroid只會(huì)觸發(fā)其中一個(gè)方法。這個(gè)理解是不太正確的,針對(duì)某個(gè)view,用戶完成了一次觸碰操作,顯然從傳感器上得到的信號(hào)是手指按下和抬起兩個(gè)操作,我們可以理解為一次Click,也可以理解為發(fā)生了一次ACTION_DOWN和ACTION_UP,那么Android是如何理解和處理的呢?

在Android中,onClick、onLongClick的觸發(fā)是和ACTION_DOWN及ACTION_UP相關(guān)的,在時(shí)序上,如果我們?cè)谝粋€(gè)View中同時(shí)覆寫了onClick、onLongClick及onTouchEvent的話,onTouchEvent是***捕捉到ACTION_DOWN和ACTION_UP事件的,其次才可能觸發(fā)onClick或者onLongClick。主要的邏輯在View.java中的onTouchEvent方法中實(shí)現(xiàn)的:

 

 
 
  1. case MotionEvent.ACTION_DOWN: 
  2.     mPrivateFlags |= PRESSED; 
  3.     refreshDrawableState(); 
  4.     if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { 
  5.          postCheckForLongClick();  
  6.     } 
  7.     break; 
  8. case MotionEvent.ACTION_UP: 
  9.     if ((mPrivateFlags & PRESSED) != 0) { 
  10.          boolean focusTaken = false; 
  11.          if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { 
  12.                focusTaken = requestFocus(); 
  13.          } 
  14.     if (!mHasPerformedLongPress) { 
  15.        if (mPendingCheckForLongPress != null) { 
  16.              removeCallbacks(mPendingCheckForLongPress); 
  17.        } 
  18.        if (!focusTaken) { 
  19.               performClick(); 
  20.        } 
  21.     } 
  22.     … 
  23.     break;

     可以看到,Click的觸發(fā)是在系統(tǒng)捕捉到ACTION_UP后發(fā)生并由performClick()執(zhí)行的,performClick里會(huì)調(diào)用先前注冊(cè)的監(jiān)聽器的onClick()方法:

 

 
 
  1. public boolean performClick() { 
  2.     … 
  3.     if (mOnClickListener != null) { 
  4.         playSoundEffect(SoundEffectConstants.CLICK); 
  5.         mOnClickListener.onClick(this); 
  6.         return true; 
  7.     } 
  8.         return false; 
  9. }

LongClick的觸發(fā)則是從ACTION_DOWN開始,由postCheckForLongClick()方法完成:

 

 
 
  1. private void postCheckForLongClick() { 
  2.      mHasPerformedLongPress = false; 
  3.      if (mPendingCheckForLongPress == null) { 
  4.          mPendingCheckForLongPress = new CheckForLongPress(); 
  5.      } 
  6.      mPendingCheckForLongPress.rememberWindowAttachCount(); 
  7.      postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout()); 

 

可以看到,在ACTION_DOWN事件被捕捉后,系統(tǒng)會(huì)開始觸發(fā)一個(gè)postDelayed操作,delay的時(shí)間在Eclair2.1上為500ms,500ms后會(huì)觸發(fā)CheckForLongPress線程的執(zhí)行:

 

 
 
  1. class CheckForLongPress implements Runnable { 
  2.  
  3. … 
  4.         public void run() { 
  5.             if (isPressed() && (mParent != null) 
  6.                     && mOriginalWindowAttachCount == mWindowAttachCount) { 
  7.                 if (performLongClick()) { 
  8.                     mHasPerformedLongPress = true; 
  9.                 } 
  10.             } 
  11.         } 
  12. … 
  13. }

如果各種條件都滿足,那么在CheckForLongPress中執(zhí)行performLongClick(),在這個(gè)方法中將調(diào)用onLongClick():

 

 
 
  1. public boolean performLongClick() { 
  2.       … 
  3.       if (mOnLongClickListener != null) { 
  4.           handled = mOnLongClickListener.onLongClick(View.this); 
  5.       } 
  6.       … 
  7. }

從實(shí)現(xiàn)中可以看到onClick()和onLongClick()方法是由ACTION_DOWN和ACTION_UP事件捕捉后根據(jù)各種情況最終確定是否觸發(fā)的,也就是說如果我們?cè)谝粋€(gè)Activity或者View中同時(shí)監(jiān)聽或者覆寫了onClick(),onLongClick()和onTouchEvent()方法,并不意味著只會(huì)發(fā)生其中一種。

下面是一個(gè)onClick被觸發(fā)的基本時(shí)序的Log:

04-05 05:57:47.123: DEBUG/TSActivity(209): onTouch ACTION_DOWN

04-05 05:57:47.263: DEBUG/TSActivity(209): onTouch ACTION_UP

04-05 05:57:47.323: DEBUG/TSActivity(209): onClick

可以看出是按ACTION_DOWN -> ACTION_UP -> onClick的次序發(fā)生的。

下面是一個(gè)onLongClick被觸發(fā)的基本時(shí)序的Log:

04-05 06:00:04.133: DEBUG/TSActivity(248): onTouch ACTION_DOWN

04-05 06:00:04.642: DEBUG/TSActivity(248): onLongClick 

04-05 06:00:05.083: DEBUG/TSActivity(248): onTouch ACTION_UP

可以看到,在保持按下的狀態(tài)一定時(shí)間后會(huì)觸發(fā)onLongClick,之后抬起手才會(huì)發(fā)生ACTION_UP。

3.  onClick和onLongClick能同時(shí)發(fā)生嗎?

     要弄清楚這個(gè)問題只要理解Android對(duì)事件處理的所謂消費(fèi)(consume)概念即可,一個(gè)用戶的操作會(huì)被傳遞到不同的View控件和同一個(gè)控件的不同監(jiān)聽方法處理,任何一個(gè)接收并處理了該次事件的方法如果在處理完后返回了true,那么該次event就算被完全處理了,其他的View或者監(jiān)聽方法就不會(huì)再有機(jī)會(huì)處理該event了。

     onLongClick的發(fā)生是由單獨(dú)的線程完成的,并且在ACTION_UP之前,而onClick的發(fā)生是在ACTION_UP后,因此同一次用戶touch操作就有可能既發(fā)生onLongClick又發(fā)生onClick。這樣是不是不可思議?所以及時(shí)向系統(tǒng)表示“我已經(jīng)完全處理(消費(fèi))了用戶的此次操作”,是很重要的事情。例如,我們?nèi)绻趏nLongClick()方法的***return true,那么onClick事件就沒有機(jī)會(huì)被觸發(fā)了。

下面的Log是在onLongClick()方法return false的情況下,一次觸碰操作的基本時(shí)序:

04-05 06:00:53.023: DEBUG/TSActivity(277): onTouch ACTION_DOWN

04-05 06:00:53.533: DEBUG/TSActivity(277): onLongClick 

04-05 06:00:55.603: DEBUG/TSActivity(277): onTouch ACTION_UP

04-05 06:00:55.663: DEBUG/TSActivity(277): onClick

可以看到,在ACTION_UP后仍然觸發(fā)了onClick()方法。


網(wǎng)站名稱:Android觸摸事件與點(diǎn)擊事件的區(qū)別
標(biāo)題路徑:http://m.5511xx.com/article/ccccsjp.html