上一篇《Android自訂群組件系列【5】——進階實踐(2)》繼續對任老師的《可下拉的PinnedHeaderExpandableListView的實現》進行了分析,這一篇計劃中間插一段“知識點”,對Android中的事件分發機制進行解析。細心的朋友可能會發現,開啟大牛寫的Android項目,裡面很多組件都是自訂的(這就是為什麼介面和體驗這麼吸引你的原因),但是要靈活的去自訂群組件就必須對手勢(也就是各種監聽)必須熟悉,能處理好事件之間的關係。
先看一段代碼:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View arg0) {Log.i(TAG, "onClick");}}); button.setOnTouchListener(new OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Log.i(TAG, "onTouch down");break;case MotionEvent.ACTION_MOVE:Log.i(TAG, "onTouch move");break;case MotionEvent.ACTION_UP:Log.i(TAG, "onTouch up");break;default:break;}return false;}}); }
可以看到onTouch方法會被先調用,然後才調用onClick方法,如果我們將上面onTouch方法的傳回值改為true,則onClick方法不會被調用,事件將被onTouch方法消費。
還記得前幾篇文章中都會使用一個dispatchTouchEvent的方法嗎.
public boolean dispatchTouchEvent(MotionEvent event) { if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && mOnTouchListener.onTouch(this, event)) { return true; } return onTouchEvent(event);}可以看到在dispatchTouchEvent中調用了onTouch方法,所以會先於onClick方法調用。如果onTouch返回true後dispatcheTouchEvent就會直接返回true則不會再執行其他方法。
在Android系統中每個ViewGroup子類都具有如下三個方法:
public boolean dispatchTouchEvent(MotionEvent event) :用來分發TouchEvent
public boolean onInterceptTouchEvent(MotionEvent event) :用來攔截TouchEvent
public boolean onTouchEvent(MotionEvent event) :處理TouchEvent
首先觸摸事件(ACTION_DOWN)發生後,系統調用Activity的dispatchTouchEvent方法,分發事件。根據觸摸事件的座標,將此事件傳遞給out(最外層)的dispatchTouchEvent處理。out則調用onInterceptTouchEvent方法判斷事件是否由自己來處理,還是向下傳遞給子View.如果out不處理該事件會根據事件產生座標分發給它的直接子View.
圖中center組件是可點擊的(clickable)組件,表示能處理Touch事件,所以center中的onInterceptTouchEvent方法將事件傳遞給center
TouchEvent中,如果傳回值是true,則說明消耗(消費)了這個事件,不會再向下傳遞。如果傳回值是false,則沒有消耗事件,會繼續傳遞下去。如果center中不會處理事件(android:clickable="false"),事件不會被center的onTouchEvent消費,則事件會層層逆向回到activity。
關於事件分發機制就先瞭解到這裡,下一篇接著分析......