Article From:

There is a Button button to set the onClick event and OnTouch event for this button.

mTestButton.setOnClickListener(new View.OnClickListener() {  
           public void onClick(View view) {  
               Log.d(TAG, "onClick execute");  
mTestButton.setOnTouchListener(new View.OnTouchListener() {  
           public boolean onTouch(View view, MotionEvent motionEvent) {  
               Log.d(TAG, "onTouch execute, action event " + motionEvent.getAction());  
               return false;  

  At this point, we are now analyzing that is onTouch first execution, or onClick execution, and then I go from the FrameWork source to explore the implementation process and principles of the whole event:

  We know that the base classes of Button, TextView, and other basic controls are all View, and as long as you touch any control, you will call the dispatchTouchEvent method of the control. When we click the button, we call it.Button class(It’s actually the base class View)InsidedispatchTouchEventSo, so look at the View source codedispatchTouchEvent()The concrete realization of the method:

public boolean dispatchTouchEvent(MotionEvent event) {  
    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&  
            mOnTouchListener.onTouch(this, event)) {  
        return true;  
    return onTouchEvent(event);  

  Analysis of the above code, second lines if the three conditions are true, then return to true, otherwise the execution of onTouchEvent, first look at the first condition mOnTouchListener! =null, this condition is if the setting of OnTouchListEner will be true, otherwise false; the second condition (mViewFlags & ENABLED_MASK) = = ENABLED is to determine whether the current click is enable, and the button is all enab by defaultLe, so this condition is invariable to true; the third conditions are more complex, mOnTouchListener.onTouch (this, event), which is actually the onTouch method when the callback control registers the touch event.That is to say, if we return to true in the onTouch method, all these three conditions will be established, so that the whole method will go back to true directly. If we return to false in the onTouch method, we will execute onTouchEvent (even) again.T) method. The onTouchEvent (MotionEvent event) method is also a method defined in view, mainly dealing with gestures passed to view, including ACTION_DOWN, ACTION_MOVEFour kinds of events, ACTION_UP, ACTION_CANCEL.

   Then we combine the specific examples above to analyze this process, first of all to execute dispatchTouchEvent (MotionEvent event), so the onTouch method is definitely earlier than the onClick method, if it is in oWhen nTouch returns to false, there will be the following phenomena:

10-20 18:57:49.670: DEBUG/MainActivity(20153): onTouch execute, action event 0
10-20 18:57:49.715: DEBUG/MainActivity(20153): onTouch execute, action event 1
10-20 18:57:49.715: DEBUG/MainActivity(20153): onClick execute

    That is to say, onTouch is executed first, then onClick event is executed, and onTouch is executed two times, one is action_down and the other is action_up event.

If onTouch returns to true, the following phenomenon occurs:

10-20 19:01:59.795: DEBUG/MainActivity(21010): onTouch execute, action event 0
10-20 19:01:59.860: DEBUG/MainActivity(21010): onTouch execute, action event 1

   The result is that the onClick event is not executed, because if onTouch returns to true, the dispatchEvent (MotionEvent event) method returns directly to true, equivalent to not passing the event, so onClick does not execute, but if onTouch returns to false (at this time the onClick method is executed), the onTouchEvent (MotionEvent event) method will be executed, and thus a conclusion can be reached, OThe specific execution of the nClick event is definitely in the source of the onTouchEvent (MotionEvent event) method. Next, we analyze the source code of the function:

 1 public boolean onTouchEvent(MotionEvent event) {  
 2     final int viewFlags = mViewFlags;  
 3     if ((viewFlags & ENABLED_MASK) == DISABLED) {  
 4         // A disabled view that is clickable still consumes the touch  
 5         // events, it just doesn't respond to them.  
 6         return (((viewFlags & CLICKABLE) == CLICKABLE ||  
 7                 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));  
 8     }  
 9     if (mTouchDelegate != null) {  
10         if (mTouchDelegate.onTouchEvent(event)) {  
11             return true;  
12         }  
13     }  
14     if (((viewFlags & CLICKABLE) == CLICKABLE ||  
15             (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {  
16         switch (event.getAction()) {  
17             case MotionEvent.ACTION_UP:  
18                 boolean prepressed = (mPrivateFlags & PREPRESSED) != 0;  
19                 if ((mPrivateFlags & PRESSED) != 0 || prepressed) {  
20                     // take focus if we don't have it already and we should in  
21                     // touch mode.  
22                     boolean focusTaken = false;  
23                     if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {  
24                         focusTaken = requestFocus();  
25                     }  
26                     if (!mHasPerformedLongPress) {  
27                         // This is a tap, so remove the longpress check  
28                         removeLongPressCallback();  
29                         // Only perform take click actions if we were in the pressed state  
30                         if (!focusTaken) {  
31                             // Use a Runnable and post this rather than calling  
32                             // performClick directly. This lets other visual state  
33                             // of the view update before click actions start.  
34                             if (mPerformClick == null) {  
35                                 mPerformClick = new PerformClick();  
36                             }  
37                             if (!post(mPerformClick)) {  
38                                 performClick();  
39                             }  
40                         }  
41                     }  
42                     if (mUnsetPressedState == null) {  
43                         mUnsetPressedState = new UnsetPressedState();  
44                     }  
45                     if (prepressed) {  
46                         mPrivateFlags |= PRESSED;  
47                         refreshDrawableState();  
48                         postDelayed(mUnsetPressedState,  
49                                 ViewConfiguration.getPressedStateDuration());  
50                     } else if (!post(mUnsetPressedState)) {  
51                         // If the post failed, unpress right now  
52               ;  
53                     }  
54                     removeTapCallback();  
55                 }  
56                 break;  
57             case MotionEvent.ACTION_DOWN:  
58                 if (mPendingCheckForTap == null) {  
59                     mPendingCheckForTap = new CheckForTap();  
60                 }  
61                 mPrivateFlags |= PREPRESSED;  
62                 mHasPerformedLongPress = false;  
63                 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());  
64                 break;  
65             case MotionEvent.ACTION_CANCEL:  
66                 mPrivateFlags &= ~PRESSED;  
67                 refreshDrawableState();  
68                 removeTapCallback();  
69                 break;  
70             case MotionEvent.ACTION_MOVE:  
71                 final int x = (int) event.getX();  
72                 final int y = (int) event.getY();  
73                 // Be lenient about moving outside of buttons  
74                 int slop = mTouchSlop;  
75                 if ((x < 0 - slop) || (x >= getWidth() + slop) ||  
76                         (y < 0 - slop) || (y >= getHeight() + slop)) {  
77                     // Outside button  
78                     removeTapCallback();  
79                     if ((mPrivateFlags & PRESSED) != 0) {  
80                         // Remove any future long press/tap checks  
81                         removeLongPressCallback();  
82                         // Need to switch from pressed to not pressed  
83                         mPrivateFlags &= ~PRESSED;  
84                         refreshDrawableState();  
85                     }  
86                 }  
87                 break;  
88         }  
89         return true;  
90     }  
91     return false;  
92 }

View Code

  Although the source code is a little bit more, we focus only on the key code, and in the 38 line we see the code: performClick (); this method is called the call of the OnClick method from the naming point of the name, and we go into the method to see whether or not the OnCl is executed.What about the ick method?

public boolean performClick() {  
    if (mOnClickListener != null) {  
        return true;  
    return false;  

  As you can see from the above code, as long as mOnClickListener is not null, it will call its onClick method, where is the mOnClickListener assigned? After analysis, the following methods are found:

public void setOnClickListener(OnClickListener l) {  
    if (!isClickable()) {  
    mOnClickListener = l;  

  And this is the method that we often use on the Application layer, that is, when we set a click event for button, we call this method and analyze it. We know that the OnClick method is actually in the OnTouchEvent method.In addition to setting up OnClickListener, what are the conditions for calling onClick? We can move forward from 38 lines of code from fourteenth lines:

    As long as the control is clickable or long by type, it goes into the branch of the MotionEvent.ACTION_UP and then passes through a variety of conditions to enter the 38 line performClick () method.

     At this point, everything is clear! When we register a click event for a control by calling the setOnClickListener method, we assign it to mOnClickListener. Then every time the control is clicked or is on time, it will be in perfor.The mClick () method callbacks the onClick method of the clicked control.

  Wise remark of an experienced person:

  The hierarchical transmission of OnTouchEvent (MotionEvent event) events. We all know that if we register a touch event for a control, every time we click on it, we will trigger a series of ACTION_DOWN, ACTION_MOVE.ACTION_UP and other events. It is important to note that if you return to false when you execute ACTION_DOWN, a series of other action will not be executed anymore. In a simple way, it’s when dispatchTouchEvent is inWhen the event is distributed, only the previous action returns true, triggering the next action.


   Then we can change a control, replace the button to ImageView, and register a touch event for it, and return to false. As shown below:



Leave a Reply

Your email address will not be published. Required fields are marked *