點擊事件會按照 Activity-window-View的順序從上到下依次傳遞,中間會有各種亂七八糟的方法調用,如果最底層也就是View在OnTouchEvent中也返回false時,然後就由Activity處理這次點擊事件,
Activity的相關源碼在這裏,下面這個是dispatchTouchEvent的源碼:
/**
* Called to process touch screen events. You can override this to
* intercept all touch screen events before they are dispatched to the
* window. Be sure to call this implementation for touch screen events
* that should be handled normally.
*
* @param ev The touch screen event.
*
* @return boolean Return true if this event was consumed.
*/
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
然後是onUserInteraction()方法,這個方法不是說的重點,雖然它也很重要,有空再說它:
/**
* Called whenever a key, touch, or trackball event is dispatched to the
* activity. Implement this method if you wish to know that the user has
* interacted with the device in some way while your activity is running.
* This callback and {@link #onUserLeaveHint} are intended to help
* activities manage status bar notifications intelligently; specifically,
* for helping activities determine the proper time to cancel a notfication.
*
* <p>All calls to your activity's {@link #onUserLeaveHint} callback will
* be accompanied by calls to {@link #onUserInteraction}. This
* ensures that your activity will be told of relevant user activity such
* as pulling down the notification pane and touching an item there.
*
* <p>Note that this callback will be invoked for the touch down action
* that begins a touch gesture, but may not be invoked for the touch-moved
* and touch-up actions that follow.
*
* @see #onUserLeaveHint()
*/
public void onUserInteraction() {
}
我們看到在dispatchTouchEvent方法中會先讓Activity的Window處理這個事件,如果一層一層傳下去後,也就是View的OnTouchEvent返回的也是false的話,getWindow().superDispatchTouchEvent(ev)這個方法返回的是false,那麼就讓這個Activity的onTouchEvent處理這個點擊事件。
需要注意的是View並沒有dispatchTouchEvent,因爲View已經是最底層了,沒必要再繼續DispatchTouchEvent了。回到原始的問題,也就是說View的onTouchEvent返回false時,會讓這個View所在的Activity處理這次點擊事件。
然後說下View幾個比較重要的容易混淆的方法先後順序:
這個是在View中定義的一個接口:
/**
* Interface definition for a callback to be invoked when a touch event is
* dispatched to this view. The callback will be invoked before the touch
* event is given to the view.
*/
public interface OnTouchListener {
/**
* Called when a touch event is dispatched to a view. This allows listeners to
* get a chance to respond before the target view.
*
* @param v The view the touch event has been dispatched to.
* @param event The MotionEvent object containing full information about
* the event.
* @return True if the listener has consumed the event, false otherwise.
*/
boolean onTouch(View v, MotionEvent event);
}
然後是自己的一個私有成員變量:
private OnTouchListener mOnTouchListener;
這個第一個方法,然後View還有個方法onTouchEvent(MotionEvent event):
/**
* Implement this method to handle touch screen motion events.
* <p>
* If this method is used to detect click actions, it is recommended that
* the actions be performed by implementing and calling
* {@link #performClick()}. This will ensure consistent system behavior,
* including:
* <ul>
* <li>obeying click sound preferences
* <li>dispatching OnClickListener calls
* <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
* accessibility features are enabled
* </ul>
*
* @param event The motion event.
* @return True if the event was handled, false otherwise.
*/
public boolean onTouchEvent(MotionEvent event) {}
還有個最常用的方法setOnclickListener(OnClickListener l):
/**
* Register a callback to be invoked when this view is clicked. If this view is not
* clickable, it becomes clickable.
*
* @param l The callback that will run
*
* @see #setClickable(boolean)
*/
public void setOnClickListener(OnClickListener l) {}
這三個方法的優先級依次是:onTouchListener中的onTouch(View v, MotionEvent event);最高,onTouchEvent(MotionEvent event) {}次之,void onClick(View v);最低。
歡迎有問題的。