Android事件分發詳解(五)——Touch事件傳遞驗證
MainActivity如下:
package cn.c;import android.os.Bundle;import android.app.Activity;import android.view.MotionEvent;/** * Demo描述: * 分析Android事件分發和處理機制 * * * 總結: * 1 ViewGroup繼承自View * 事件的傳遞方向為:從最外層(Activity)傳遞至最內層(某個View) * 事件的消費方向為:從最內層(某個View)傳遞至最外層(Activity) * 該兩個方向是相反的 * 2 ViewGroup中事件處理的流程是: * dispatchTouchEvent->onInterceptTouchEvent->onTouchEvent * View中事件處理的流程是: * dispatchTouchEvent->onTouchEvent * 3 ViewGroup中onInterceptTouchEvent預設值是false * 表示未攔截 * ViewGroup中onTouchEvent預設值是false * 表示未消費 * View中onTouchEvent返回預設值是true * 表示已消費 * * 小結: * (1) 每一次的ACTION_DOWN和ACTION_MOVE以及ACTION_UP都會引起每一層的dispatchTouchEvent() * 所以:dispatchTouchEvent()的順序是由上至下的!!!!!!!!!!!!!!! * (2) 但是每一層的onTouchEvent()就不一定會執行了.比如下層已經消耗掉了事件,那麼上層就不會響應onTouchEvent()了. * 所以:onTouchEvent()是從下到上回溯的.當然前提是事件沒有被消費的情況下!!!!!!!!!!!!! * * 在該樣本中涉及到三個自訂的View.分別是: * 最外層的布局MyFrameLayout * 內層的布局MyLinearLayout * 最裡層的自訂按鈕MyButton * * 現在進行一系列的測試並對現象進行解釋 * * 測試一: * 在MyFrameLayout的dispatchTouchEvent()方法中直接返回false. * 那麼可以看到MyFrameLayout的onInterceptTouchEvent()和onTouchEvent()都沒有執行. * MyFrameLayout所包含的子View對於Touch事件也當然沒有任何的反映. * 其實這樣直接返回false是挺殘暴的.因為重寫了該方法,使得源碼中dispatchTouchEvent()方法裡的 * 一大堆代碼都沒有執行,所以它的onInterceptTouchEvent()和onTouchEvent()都沒有調用也就沒有 * 什麼事件的繼續分發了. * 因為它直接給Activity返回了false即連ACTION_DOWN事件都沒有處理.所以後續的事件比如ACTION_DOWN和ACTION_UP * 都沒有資格處理,都是直接由Activity處理了. * * * 測試二: * 在MyFrameLayout的dispatchTouchEvent()方法中調用:super.dispatchTouchEvent(ev); * 且返回return super.dispatchTouchEvent(ev); * 在MyFrameLayout的onInterceptTouchEvent()方法中直接返回return true;表示攔截 * 可以看到事件的分發到了MyFrameLayout就停止了,不會向其子View派發. * * 其餘的驗證將在下一個例子中給出. * */public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); System.out.println(===> MainActivity 中調用 onCreate()); System.out.println(--------------------------------------------------); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { System.out.println(===> MainActivity 中調用 dispatchTouchEvent());System.out.println(===> super.dispatchTouchEvent()預設返回true);System.out.println(--------------------------------------------------); return super.dispatchTouchEvent(ev); }@Overridepublic void onUserInteraction() {System.out.println(===> MainActivity 中調用 onUserInteraction());System.out.println(--------------------------------------------------);super.onUserInteraction();}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:System.out.println(===> MainActivity 中調用 onTouchEvent()--->ACTION_DOWN);break;case MotionEvent.ACTION_MOVE:System.out.println(===> MainActivity 中調用 onTouchEvent()--->ACTION_MOVE);break;case MotionEvent.ACTION_UP:System.out.println(===> MainActivity 中調用 onTouchEvent()--->ACTION_UP);default:break;}System.out.println(super.onTouchEvent()預設返回false 表示未消費事件);System.out.println(--------------------------------------------------);return super.onTouchEvent(event);}}
MyFrameLayout如下:
package cn.c;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.FrameLayout;public class MyFrameLayout extends FrameLayout{public MyFrameLayout(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {super.dispatchTouchEvent(ev);System.out.println(外層MyFrameLayout 中調用 dispatchTouchEvent());System.out.println(super.dispatchTouchEvent()預設返回true 表示繼續分發);System.out.println(--------------------------------------------------);return super.dispatchTouchEvent(ev);//return false;}//覆寫自ViewGroup@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {System.out.println(外層MyFrameLayout 中調用 onInterceptTouchEvent());System.out.println(super.onInterceptTouchEvent()預設返回false 表示不攔截);System.out.println(--------------------------------------------------);//return super.onInterceptTouchEvent(ev);return true;}//注意://1 ViewGroup是View的子類//2 ViewGroup中onTouchEvent()方法預設返回的是false@Overridepublic boolean onTouchEvent(MotionEvent event) {super.onTouchEvent(event);switch (event.getAction()) {case MotionEvent.ACTION_DOWN:System.out.println(外層MyFrameLayout 中調用 onTouchEvent()--->ACTION_DOWN);break;case MotionEvent.ACTION_MOVE:System.out.println(外層MyFrameLayout 中調用 onTouchEvent()--->ACTION_MOVE);break;case MotionEvent.ACTION_UP:System.out.println(外層MyFrameLayout 中調用 onTouchEvent()--->ACTION_UP);default:break;}System.out.println(super.onTouchEvent()預設返回false 表示未消費事件);System.out.println(--------------------------------------------------);return super.onTouchEvent(event);//return true;}}
MyLinearLayout如下:
package cn.c;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.LinearLayout;public class MyLinearLayout extends LinearLayout {public MyLinearLayout(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {super.dispatchTouchEvent(ev);System.out.println(內層MyLinearLayout 中調用 dispatchTouchEvent());System.out.println(super.dispatchTouchEvent()預設返回true 表示繼續分發);System.out.println(--------------------------------------------------);//return super.dispatchTouchEvent(ev);return false;}//覆寫自ViewGroup@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {super.onInterceptTouchEvent(ev);System.out.println(內層MyLinearLayout 中調用 onInterceptTouchEvent());System.out.println(super.onInterceptTouchEvent()預設返回false 表示不攔截);System.out.println(--------------------------------------------------);return super.onInterceptTouchEvent(ev);}//注意://1 ViewGroup是View的子類//2 ViewGroup中onTouchEvent()方法預設返回的是false@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:System.out.println(內層MyLinearLayout 中調用 onTouchEvent()--->ACTION_DOWN);break;case MotionEvent.ACTION_MOVE:System.out.println(內層MyLinearLayout 中調用 onTouchEvent()--->ACTION_MOVE);break;case MotionEvent.ACTION_UP:System.out.println(內層MyLinearLayout 中調用 onTouchEvent()--->ACTION_UP);default:break;}System.out.println(super.onTouchEvent()預設返回false 表示未消費事件);System.out.println(--------------------------------------------------);return super.onTouchEvent(event);}}
MyButton如下:
package cn.c;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.Button;public class MyButton extends Button{public MyButton(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {System.out.println(自訂Button 中調用 dispatchTouchEvent());System.out.println(super.dispatchTouchEvent預設返回true);System.out.println(--------------------------------------------------);return super.dispatchTouchEvent(event);}//注意://在View的子類中onTouchEvent()方法預設返回的是true@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:System.out.println(自訂Button 中調用 onTouchEvent()--->ACTION_DOWN);break;case MotionEvent.ACTION_MOVE:System.out.println(自訂Button 中調用 onTouchEvent()--->ACTION_MOVE);break;case MotionEvent.ACTION_UP:System.out.println(自訂Button 中調用 onTouchEvent()--->ACTION_UP);break;default:break;}System.out.println(super.onTouchEvent()預設返回true);System.out.println(--------------------------------------------------);return super.onTouchEvent(event);}}
上一篇http://www.bkjia.com/kf/201412/365604.html