Android TouchEvent事件傳遞機制

來源:互聯網
上載者:User

標籤:

跟touch事件相關的3個方法: public boolean dispatchTouchEvent(MotionEvent ev);    //用來指派event public boolean onInterceptTouchEvent(MotionEvent ev); //用來攔截event public boolean onTouchEvent(MotionEvent ev);          //用來處理event  擁有這三個方法的類:
Activity類: Activity dispatchTouchEvent();
onTouchEvent();
View容器(ViewGroup的子類): FrameLayout、LinearLayout……
ListView、ScrollVIew……
dispatchTouchEvent();
onInterceptTouchEvent();
onTouchEvent();
View控制項(非ViewGroup子類): Button、TextView、EditText…… dispatchTouchEvent();
onTouchEvent();

個方 法的用法:
dispatchTouchEvent() 用來指派事件。
其中調用了onInterceptTouchEvent()和onTouchEvent(),一般不重寫該方法
onInterceptTouchEvent() 用來攔截事件。
ViewGroup類中的源碼實現就是{return false;}表示不攔截該事件,
事件將向下傳遞(傳遞給其子View);
若手動重寫該方法,使其返回true則表示攔截,事件將終止向下傳遞,
事件由當前ViewGroup類來處理,就是調用該類的onTouchEvent()方法
onTouchEvent() 用來處理事件。
返回true則表示該View能處理該事件,事件將終止向上傳遞(傳遞給其父View);
返回false表示不能處理,則把事件傳遞給其父View的onTouchEvent()方法來處理
【注】:ViewGroup的某些子類(GridView、ScrollView...)重寫了onInterceptTouchEvent()方法,當發生ACTION_MOVE事件時,返回true進行攔截。   為了示範,重寫了4個類:總統 --> MyActivity省長 --> MyFrameLayout市長 --> MyLinearLayout農民 --> MyTextView
 【舉個通俗易懂的例子】:總統對省長說:我要吃紅燒魚省長對市長說:你做個紅燒魚市長對縣長說:你做個紅燒魚縣長對農民說:你做個紅燒魚   ……(農民做呀做,沒做出來)農民說:我儘力了,但真心不會做呀,饒了我吧縣長說:你個笨蛋,下次不找你了,看我來做   ……(縣長做呀做,沒做出來)縣長對市長說:我儘力了,非常抱歉,我不會做市長說:你個廢物,要你何用,只能我自己來做了   ……(市長做呀做,做成功了)市長對省長說:紅燒魚做好了省長說:不錯,下次有事還找你省長對總統說:紅燒魚做好了總統說:不錯,下次有事還找你 ---------------------------總統對省長說:我要吃水煮魚省長對市長說:你做個水煮魚市長說:縣長連紅燒魚都搞不定,這次就不找他了,我自己親自來做 ……(市長做呀做,又成功了) 市長對省長說:水煮魚做好了省長說:不錯,下次有事還找你省長對總統說:水煮魚做好了總統說:不錯,下次有事還找你 ---------------------------
  • 按常理,領導都會把任務向下指派,一旦下面的人把事情做不好,就不會再把後續的任務交給下面的人來做了,只能自己親自做,如果自己也做不了,就只能告訴上級不能完成任務,上級又會重複他的過程。
  • 另外,領導都有權利攔截任務,對下級隱瞞該任務,而直接自己去做,如果做不成,也只能向上級報告不能完成任務。
【1】TextView的clickable屬性預設是false,所以TextView的onTouchEvent()方法預設返回false,程式輸出如下:     事件傳遞:
  【2】把TextView的clickable屬性手動改成true,或者直接重寫onTouchEvent()方法,使其返回true,程式輸出如下:
      事件傳遞:
  【3】手動重寫LinearLayout的onInterceptTouchEvent()方法,使其返回true,攔截事件,再重寫onTouchEvent()方法,返回true,程式輸出:
      事件傳遞:
 (1)這一系列的傳遞流程都是dispatchTouchEvent()方法來控制的,如果不人為地幹預,事件將由上自下依次傳遞(因為預設是返回false不會攔截的),傳遞到最底層的View,就由它的onTouchEvent()方法來處理事件,若處理成功返回true,若處理失敗返回false,事件依次向上傳遞,每個View都調用自己的onTouchEvent()方法來處理事件,若處理成功就終止傳遞,若處理失敗就繼續向上傳遞。(2)經過人為的幹預,若在向下傳遞的過程中被攔截了,即onInterceptTouchEvent()方法返回true,則事件將停止向下傳遞,直接由當前的onTouchEvent()方法來處理,若處理成功則OK,若處理不成功,則事件會向上傳遞。(3)另外,dispatchTouchEvent()方法中還有“記憶”的功能,如果第一次事件向下傳遞到某View,它把事件繼續傳遞交給它的子View,它會記錄該事件是否被它下面的View給處理成功了,(怎麼能知道呢?如果該事件會再次被向上傳遞到我這裡來由我的onTouchEvent()來處理,那就說明下面的View都沒能成功處理該事件);當第二次事件向下傳遞到該View,該View的dispatchTouchEvent()方法機會判斷,若上次的事件由下面的view成功處理了,那麼這次的事件就繼續交給下面的來處理,若上次的事件沒有被下面的處理成功,那麼這次的事件就不會向下傳遞了,該View直接調用自己的onTouchEvent()方法來處理該事件。(4)“記憶”功能的資訊只在一系列事件完成之前有效,如從ACTION_DOWN事件開始,直到後續事件ACTION_MOVE,ACTION_UP結束後,“記憶”的資訊就會清除。也就是說如果某View處理ACTION_DOWN事件失敗了(onTouchEvent()返回false),那麼後續的ACTION_MOVE,ACTION_UP等事件就不會再傳遞到該View了,由其父View自己來處理。在下一次發生ACTION_DOWN事件的時候,還是會傳遞到該View的。 Demo源碼下載:http://download.csdn.net/detail/morgan_xww/5781199 [java] view plaincopyprint? 
  1. public class MyActivity extends Activity {  
  2.       
  3.     @Override  
  4.     public void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.main);  
  7.     }  
  8.       
  9.     @Override  
  10.     public boolean dispatchTouchEvent(MotionEvent ev) {  
  11.         Log.d("d", "【總統】任務<" + Util.actionToString(ev.getAction()) + "> : 需要指派");  
  12.         return super.dispatchTouchEvent(ev);  
  13.     }  
  14.       
  15.     @Override  
  16.     public boolean onTouchEvent(MotionEvent ev) {  
  17.         boolean bo = false;  
  18.         Log.d("d", "【總統】任務<" + Util.actionToString(ev.getAction()) + "> : 下面都解決不了,下次再也不能靠你們了,哼…只能自己嘗試一下啦。能解決?" + bo);  
  19.         return bo;  
  20.     }  
  21. }  

[java] view plaincopyprint? 
  1. public class MyFrameLayout extends FrameLayout  
  2. {  
  3.     public MyFrameLayout(Context context, AttributeSet attrs){  
  4.         super(context, attrs);  
  5.     }  
  6.       
  7.     @Override  
  8.     public boolean dispatchTouchEvent(MotionEvent ev) {  
  9.         Log.d("d", "【省長】任務<" + Util.actionToString(ev.getAction()) + "> : 需要指派");  
  10.         return super.dispatchTouchEvent(ev);  
  11.     }  
  12.   
  13.     @Override  
  14.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  15.         boolean bo = false;  
  16.         Log.d("d", "【省長】任務<" + Util.actionToString(ev.getAction()) + "> : 攔截嗎?" + bo);  
  17.         return bo;  
  18.     }  
  19.   
  20.     @Override  
  21.     public boolean onTouchEvent(MotionEvent ev) {  
  22.         boolean bo = false;  
  23.         Log.d("d", "【省長】任務<" + Util.actionToString(ev.getAction()) + "> : 市長是個廢物,下次再也不找你了,我自己來嘗試一下。能解決?" + bo);  
  24.         return bo;  
  25.     }  
  26. }  

[java] view plaincopyprint? 
  1. public class MyLinearLayout extends LinearLayout{  
  2.       
  3.     public MyLinearLayout(Context context, AttributeSet attrs) {  
  4.         super(context, attrs);  
  5.     }  
  6.       
  7.     @Override  
  8.     public boolean dispatchTouchEvent(MotionEvent ev) {  
  9.         Log.d("d", "【市長】任務<" + Util.actionToString(ev.getAction()) + "> : 需要指派");  
  10.         return super.dispatchTouchEvent(ev);  
  11.     }  
  12.   
  13.     @Override  
  14.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  15.         boolean bo = false;  
  16.         Log.d("d", "【市長】任務<" + Util.actionToString(ev.getAction()) + "> : 攔截嗎?" + bo);  
  17.         return bo;  
  18.     }  
  19.   
  20.     @Override  
  21.     public boolean onTouchEvent(MotionEvent ev) {  
  22.         boolean bo = false;  
  23.         Log.d("d", "【市長】任務<" + Util.actionToString(ev.getAction()) + "> : 農民真沒用,下次再也不找你了,我自己來嘗試一下。能解決?" + bo);  
  24.         return bo;  
  25.     }  
  26. }  

[java] view plaincopyprint? 
  1. public class MyTextView extends TextView  
  2. {  
  3.     public MyTextView(Context context, AttributeSet attrs){  
  4.         super(context, attrs);  
  5.     }  
  6.       
  7.     @Override  
  8.     public boolean dispatchTouchEvent(MotionEvent ev){  
  9.         Log.d("d", "【農民】任務<" + Util.actionToString(ev.getAction()) + "> : 需要指派,我下面沒人了,怎麼辦?自己幹吧");  
  10.         return super.dispatchTouchEvent(ev);  
  11.     }  
  12.       
  13.     @Override  
  14.     public boolean onTouchEvent(MotionEvent ev){  
  15.         boolean bo = true;  
  16.         Log.d("d", "【農民】任務<" + Util.actionToString(ev.getAction()) + "> : 自己動手,埋頭苦幹。能解決?" + bo);  
  17.         return bo;  
  18.     }  
  19. }  

Android TouchEvent事件傳遞機制

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.