Custom view event distribution

Each subclass of ViewGroup in android has three methods related to TouchEvent:

1.public boolean dispatchTouchEvent(MotionEvent event) This method is used to distribute TouchEvent

2.public boolean onInterceptTouchEvent(MotionEvent event) This method is used to intercept TouchEvent

3.public boolean onTouchEvent(MotionEvent event) This method is used to handle TouchEvent

Note: Not all View subclasses. Only the controls that can add View to it need to be distributed. For example, TextView itself is the smallest view, so there is no need to distribute to its subviews, and it has no subviews. So it does not have dispatch and Intercept, only touchEvent.

Give a simple example: (an activity, a button in the layout)

Monitor the button

 button.setOnClickListener(new OnClickListener() {
     @Override
   public void onClick(View v) {
        Log.d("TAG", " onClick");
     }
});


Add a touch event to the button

 button.setOnTouchListener(new OnTouchListener() {
     @Override
    public boolean onTouch(View v, MotionEvent event) {
         Log.d("TAG", "onTouch " + event.getAction());
         return false;
     }
 });

The execution results are as follows:
onTouch 0 is equivalent to down
onTouch 1 is equivalent to up
onClick click event
It can be seen from the above results: the order of event delivery is first through onTouch, and then to onClick
When onTouch return false means that you have not consumed the onTouch event. After executing the code in your onTouch, the onTouch event has not ended.
When onTouch returns true, it means that the event was consumed by onTouch and will not continue to pass down.

Then look at the source code of dispatchTouchEvent

    /**
      * Pass the touch screen motion event down to the target view, or this
      * view if it is the target.
      * @param event The motion event to be dispatched.
      * @return True if the event was handled by the view, false otherwise.
      */
     public boolean dispatchTouchEvent(MotionEvent event) {
         if (!onFilterTouchEventForSecurity(event)) {
             return false;
        }
         if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
                 mOnTouchListener.onTouch(this, event)) {
            return true;
         }
         return onTouchEvent(event);
    }
1. OnTouchListener is set in the setOnTouchListener method, in fact it is the setOnTouchListener we just set in Activity, which means that as long as we register the touch event for the control, mOnTouchListener must be assigned a value

2. The second condition is to judge whether the control is enabled. The button is true even if it is Enabled by default.

3. The third condition is the key. This condition will call back the onTouch method when the control registers the touch event. The key here is to see the return value of the onTouch method.

Another important question is the level transmission of Touch events. If you register a touch event for a control, a series of ACTION_DOWN, ACTION_MOVE, ACTION_UP and other events will be triggered every time you click on it. If you return false when executing ACTION_DOWN, a series of other actions will not be executed again. Up. Simply put, when dispatchTouchEvent is in the process of event distribution, only the previous action returns true will the next action be triggered.

Guess you like

Origin blog.csdn.net/xifei66/article/details/54583247