View's Event Distribution Mechanism

Keywords: Android

1. Analyzing the execution process of event passing related methods through log

To better understand the event delivery of view, we can customize a button to inherit from Button, and rewrite the event delivery related methods to analyze the execution order of each method by logging.
Custom button, rewrite dispatchTouchEvent and onTouchEvent view plain copy
  1. public class MyButton extends Button {  
  2.     public MyButton(Context context, AttributeSet attrs) {  
  3.         super(context, attrs);  
  4.     }  
  5.   
  6.     @Override  
  7.     public boolean dispatchTouchEvent(MotionEvent event) {  
  8.         switch (event.getAction()) {  
  9.             case MotionEvent.ACTION_DOWN:  
  10.                 Log.d("dispatchTouchEvent""ACTION_DOWN");  
  11.                 break;  
  12.             case MotionEvent.ACTION_MOVE:  
  13.                 Log.d("dispatchTouchEvent""ACTION_MOVE");  
  14.                 break;  
  15.             case MotionEvent.ACTION_UP:  
  16.                 Log.d("dispatchTouchEvent""ACTION_UP");  
  17.                 break;  
  18.         }  
  19.         return super.dispatchTouchEvent(event);  
  20.     }  
  21.   
  22.     @Override  
  23.     public boolean onTouchEvent(MotionEvent event) {  
  24.         switch (event.getAction()) {  
  25.             case MotionEvent.ACTION_DOWN:  
  26.                 Log.d("onTouchEvent""ACTION_DOWN");  
  27.                 break;  
  28.             case MotionEvent.ACTION_MOVE:  
  29.                 Log.d("onTouchEvent""ACTION_MOVE");  
  30.                 break;  
  31.             case MotionEvent.ACTION_UP:  
  32.                 Log.d("onTouchEvent""ACTION_UP");  
  33.                 break;  
  34.         }  
  35.         return super.onTouchEvent(event);  
  36.     }  
  37. }  
Add a custom button to the layout
  1. <LinearLayout  
  2.     xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:tools="http://schemas.android.com/tools"  
  4.     android:id="@+id/activity_main"  
  5.     android:layout_width="match_parent"  
  6.     android:layout_height="match_parent"  
  7.     tools:context="com.tfx.test.MainActivity">  
  8.   
  9.     <com.tfx.test.MyButton  
  10.         android:id="@+id/bt"  
  11.         android:layout_width="wrap_content"  
  12.         android:layout_height="wrap_content"  
  13.         android:text="button"/>  
  14. </LinearLayout>  
MainActivity code to register setOnTouchEvent listeners for custom button s
  1. public class MainActivity extends AppCompatActivity {  
  2.     @Override  
  3.     protected void onCreate(Bundle savedInstanceState) {  
  4.         super.onCreate(savedInstanceState);  
  5.         setContentView(R.layout.activity_main);  
  6.         Button button = (Button) findViewById(R.id.bt);  
  7.         button.setOnTouchListener(new View.OnTouchListener() {  
  8.             @Override  
  9.             public boolean onTouch(View view, MotionEvent motionEvent) {  
  10.                 switch (motionEvent.getAction()) {  
  11.                     case MotionEvent.ACTION_DOWN:  
  12.                         Log.d("onTouch""ACTION_DOWN");  
  13.                         break;  
  14.   
  15.                     case MotionEvent.ACTION_MOVE:  
  16.                         Log.d("onTouch""ACTION_MOVE");  
  17.                         break;  
  18.   
  19.                     case MotionEvent.ACTION_UP:  
  20.                         Log.d("onTouch""ACTION_UP");  
  21.                         break;  
  22.                 }  
  23.                 return false;  
  24.             }  
  25.         });  
  26.     }  
  27. }  
After rewriting the three event distribution related methods, run demo and click the button button button, and then look at the output log
  1. 12-19 09:22:56.478 1837-1837/com.tfx.test D/dispatchTouchEvent: ACTION_DOWN  
  2. 12-19 09:22:56.478 1837-1837/com.tfx.test D/onTouch: ACTION_DOWN  
  3. 12-19 09:22:56.478 1837-1837/com.tfx.test D/onTouchEvent: ACTION_DOWN  
  4. 12-19 09:22:56.556 1837-1837/com.tfx.test D/dispatchTouchEvent: ACTION_UP  
  5. 12-19 09:22:56.556 1837-1837/com.tfx.test D/onTouch: ACTION_UP  
  6. 12-19 09:22:56.556 1837-1837/com.tfx.test D/onTouchEvent: ACTION_UP  
If you rub your finger slightly when you click the button, you will perform multiple move s, as follows
  1. 12-19 09:20:17.253 1837-1837/com.tfx.test D/dispatchTouchEvent: ACTION_DOWN  
  2. 12-19 09:20:17.253 1837-1837/com.tfx.test D/onTouch: ACTION_DOWN  
  3. 12-19 09:20:17.253 1837-1837/com.tfx.test D/onTouchEvent: ACTION_DOWN  
  4. 12-19 09:20:17.295 1837-1837/com.tfx.test D/dispatchTouchEvent: ACTION_MOVE  
  5. 12-19 09:20:17.296 1837-1837/com.tfx.test D/onTouch: ACTION_MOVE  
  6. 12-19 09:20:17.296 1837-1837/com.tfx.test D/onTouchEvent: ACTION_MOVE  
  7. 12-19 09:20:17.463 1837-1837/com.tfx.test D/dispatchTouchEvent: ACTION_MOVE  
  8. 12-19 09:20:17.463 1837-1837/com.tfx.test D/onTouch: ACTION_MOVE  
  9. 12-19 09:20:17.463 1837-1837/com.tfx.test D/onTouchEvent: ACTION_MOVE  
  10. 12-19 09:20:17.580 1837-1837/com.tfx.test D/dispatchTouchEvent: ACTION_MOVE  
  11. 12-19 09:20:17.580 1837-1837/com.tfx.test D/onTouch: ACTION_MOVE  
  12. 12-19 09:20:17.580 1837-1837/com.tfx.test D/onTouchEvent: ACTION_MOVE  
  13. 12-19 09:20:17.716 1837-1837/com.tfx.test D/dispatchTouchEvent: ACTION_UP  
  14. 12-19 09:20:17.717 1837-1837/com.tfx.test D/onTouch: ACTION_UP  
  15. 12-19 09:20:17.717 1837-1837/com.tfx.test D/onTouchEvent: ACTION_UP  
From the logs, we can see that the processes of down, move and up are dispatch TouchEvent - > onTouch - > onTouchEvent.
onTouchListener's onTouch method has a return value. If you change the return value to return true and run it again, you will find that the onTouchEvent method can not be executed. Why? If you register the click event with the button at this time, you will find that the click event will not be triggered. Why? With these two problems in mind, we will analyze the dispatch TouchEvent method.

2. dispatch TouchEvent method

When we enter the parent TextView of button, we don't find this method. We continue to look in its parent view, and then we can see the source code of the dispatchTouchEvent method, as follows:
  1. public boolean dispatchTouchEvent(MotionEvent event) {    
  2.     if (!onFilterTouchEventForSecurity(event)) {    
  3.         return false;    
  4.     }    
  5.   
  6.     if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&    
  7.             mOnTouchListener.onTouch(this, event)) {    
  8.         return true;    
  9.     }    
  10.     return onTouchEvent(event);    
  11. }  
Considering the second if statement, there are three conditions:
Conditions 1: Make a non-empty judgment on mOnTouchListener, that is, whether the onTouchListener monitor is registered or not.
Conditions 2: Judging whether view is enable or not, common controls are all enable by default?
Conditional 3: Determine whether the onTouch method of onTouchEvent returns true
If all three conditions hold, the dispatchTouchEvent method returns true, otherwise onTouchEvent is executed and returned.
Next, the first question is that when all three conditions are met, the dispatchTouchEvent method will return true, and the onTouchEvent method will not be executed. That is to say, the return value of onTouchEvent method of onTouchListener determines whether the onTouchEvent method can be executed or not. If the true event is returned, it will be consumed and will not be passed on to onTouchEvent method. By default, the onTouchEvent method will return fals. E, the onTouchEvent method will be executed, and the first problem is solved here.
Next, we can conclude that the onClick method of the click event is executed in the onTouchEvent method. Only when the onTouchEvent method is executed, can the onTouchEvent method respond to the click event. And the onTouch method takes precedence over the onClick method. The onTouch method does more than the onClick method, and can respond to dowm, move, up gestures.

3.onTouchEvent Method


Posted by saranya on Thu, 11 Apr 2019 16:48:32 -0700