Android TouchEvent事件傳遞機制
跟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
【舉個通俗易懂的例子】:
總統對省長說:我要吃紅燒魚
省長對市長說:你做個紅燒魚
市長對縣長說:你做個紅燒魚
縣長對農民說:你做個紅燒魚
……(農民做呀做,沒做出來)
農民說:我盡力了,但真心不會做呀,饒了我吧
縣長說:你個笨蛋,下次不找你了,看我來做
……(縣長做呀做,沒做出來)
縣長對市長說:我盡力了,非常抱歉,我不會做
市長說:你個廢物,要你何用,只能我自己來做了
……(市長做呀做,做成功了)
市長對省長說:紅燒魚做好了
省長說:不錯,下次有事還找你
省長對總統說:紅燒魚做好了
總統說:不錯,下次有事還找你
---------------------------
總統對省長說:我要吃水煮魚
省長對市長說:你做個水煮魚
市長說:縣長連紅燒魚都搞不定,這次就不找他了,我自己親自來做
……(市長做呀做,又成功了)
市長對省長說:水煮魚做好了
省長說:不錯,下次有事還找你
省長對總統說:水煮魚做好了
總統說:不錯,下次有事還找你
---------------------------
- 按常理,領導都會把任務向下分派,一旦下面的人把事情做不好,就不會再把後續的任務交給下面的人來做了,只能自己親自做,如果自己也做不了,就只能告訴上級不能完成任務,上級又會重複他的過程。
- 另外,領導都有權利攔截任務,對下級隱瞞該任務,而直接自己去做,如果做不成,也只能向上級報告不能完成任務。
【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的。
- public class MyActivity extends Activity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- }
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- Log.d("d", "【總統】任務<" + Util.actionToString(ev.getAction()) + "> : 需要分派");
- return super.dispatchTouchEvent(ev);
- }
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- boolean bo = false;
- Log.d("d", "【總統】任務<" + Util.actionToString(ev.getAction()) + "> : 下面都解決不了,下次再也不能靠你們了,哼…只能自己嘗試一下啦。能解決?" + bo);
- return bo;
- }
- }
- public class MyFrameLayout extends FrameLayout
- {
- public MyFrameLayout(Context context, AttributeSet attrs){
- super(context, attrs);
- }
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- Log.d("d", "【省長】任務<" + Util.actionToString(ev.getAction()) + "> : 需要分派");
- return super.dispatchTouchEvent(ev);
- }
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- boolean bo = false;
- Log.d("d", "【省長】任務<" + Util.actionToString(ev.getAction()) + "> : 攔截嗎?" + bo);
- return bo;
- }
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- boolean bo = false;
- Log.d("d", "【省長】任務<" + Util.actionToString(ev.getAction()) + "> : 市長是個廢物,下次再也不找你了,我自己來嘗試一下。能解決?" + bo);
- return bo;
- }
- }
- public class MyLinearLayout extends LinearLayout{
- public MyLinearLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev) {
- Log.d("d", "【市長】任務<" + Util.actionToString(ev.getAction()) + "> : 需要分派");
- return super.dispatchTouchEvent(ev);
- }
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- boolean bo = false;
- Log.d("d", "【市長】任務<" + Util.actionToString(ev.getAction()) + "> : 攔截嗎?" + bo);
- return bo;
- }
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- boolean bo = false;
- Log.d("d", "【市長】任務<" + Util.actionToString(ev.getAction()) + "> : 農民真沒用,下次再也不找你了,我自己來嘗試一下。能解決?" + bo);
- return bo;
- }
- }
- public class MyTextView extends TextView
- {
- public MyTextView(Context context, AttributeSet attrs){
- super(context, attrs);
- }
- @Override
- public boolean dispatchTouchEvent(MotionEvent ev){
- Log.d("d", "【農民】任務<" + Util.actionToString(ev.getAction()) + "> : 需要分派,我下面沒人了,怎麼辦?自己幹吧");
- return super.dispatchTouchEvent(ev);
- }
- @Override
- public boolean onTouchEvent(MotionEvent ev){
- boolean bo = true;
- Log.d("d", "【農民】任務<" + Util.actionToString(ev.getAction()) + "> : 自己動手,埋頭苦幹。能解決?" + bo);
- return bo;
- }
- }
相關文章
- Android觸控事件傳遞機制Android事件
- Android10_原理機制系列_事件傳遞機制Android事件
- Android中觸控事件的傳遞機制Android事件
- android的TouchEvent派發機制的分析Android
- 用一張圖告訴你Android中的事件傳遞機制Android事件
- 【朝花夕拾】Android自定義View篇之(五)Android事件分發及傳遞機制AndroidView事件
- Android之Handler訊息傳遞機制詳解Android
- iOS 中的事件傳遞和響應機制 - 原理篇iOS事件
- iOS 中的事件傳遞和響應機制 - 實踐篇iOS事件
- iOS 中的事件傳遞和響應機制 – 實踐篇iOS事件
- Android事件分發機制Android事件
- Android Handler訊息傳遞機制:圖文解析工作原理Android
- android 訊息傳遞機制進階EventBus的深入探究Android
- flutter 訊息傳遞機制Flutter
- Handler訊息傳遞機制
- 從事件驅動程式設計模型分析Handler訊息傳遞機制事件程式設計模型
- 引數傳遞機制之JWTJWT
- Android 事件分發機制的理解Android事件
- android事件分發機制詳解Android事件
- Android的MotionEvent事件分發機制Android事件
- Android View 的事件體系 -- 事件分發機制AndroidView事件
- Android事件分發機制簡單理解Android事件
- 淺談Android 事件分發機制(二)Android事件
- 【Android基礎】講講Android的事件分發機制Android事件
- Android事件分發機制三:事件分發工作流程Android事件
- Netty使用及事件傳遞Netty事件
- React事件傳遞引數React事件
- 淺談Android中的事件分發機制Android事件
- 淺談JS事件機制與React事件機制JS事件React
- Android事件分發機制,你瞭解過嗎?Android事件
- Android 事件分發機制原始碼解析-view層Android事件原始碼View
- 面試:講講 Android 的事件分發機制面試Android事件
- 事件傳遞和響應鏈事件
- Android事件分發:從原始碼角度分析View事件分發機制Android事件原始碼View
- DOM事件機制事件
- redis事件機制Redis事件
- react事件機制React事件
- Android從原始碼角度剖析View事件分發機制Android原始碼View事件
- Android 事件分發機制原始碼詳解-最新 APIAndroid事件原始碼API