Android MotionEvent Event Response Mechanism

Source: Internet
Author: User

In android, events mainly include click, long press, drag, and slide operations. These constitute Android event responses. In general, all events are composed of the following three parts:

Press (action_down), move (action_move), and lift (action_up ). All the responses are based on View and ViewGroup. The response methods are as follows:

In View. java:

Publi boolean dispatchTouchEvent (MotionEvent event)
Public boolean onTouchEvent (MotionEvent event)

ViewGroup. java

Public boolean dispatchTouchEvent (MotionEvent event)
Public boolean onTouchEvent (MotionEvent event)
Public boolean onInterceptTouchEvent (MotionEvent event)

When the component is nested, the response to the event is continuously transmitted from the top-level component to the child component until the final View component.

We can see that the ViewGroup has an onInterceptTouchEvent method more than the View. This is because the ViewGroup component can have child components. Therefore, you need to use Intercept to determine whether to pass the event to the child component.

The specific functions of a function are as follows:

OnTouchEvent is actually used for business logic processing. If it returns true, it indicates that the event has been consumed. If it returns false, it indicates that the event continues to be transmitted.

OnInterceptTouchEvent is used to determine whether to intercept the event to prevent it from continuing to pass to the child component. If false is returned, the dispatchTouchEvent method of the child component is called recursively; if true is returned, the onTouchEvent method of this component is called for processing.

The above two functions are relatively easy to understand. The most important thing is the third one. I have read a lot on the Internet before, but I have not made it very clear. Most of them are used for event distribution. If true is returned, the distribution is not resumed. If false is returned, the distribution is resumed. But I have never understood the difference between this and onInterceptTouchEvent ..

Simply put, Android handles touch events through recursion, which is embodied in dispatchTouchEvent. The two functions mentioned above are called in the dispatchTouchEvent and executed to implement the business logic for distribution.

Three methods may be called in dispatchTouchEvent:

1. onInterceptTouchEvent of this component

2. dispatchTouchEvent of the child component

3. onTouchEvent of this component

The execution logic of dispatchTouchEvent () in ViewGroup:

1. First, execute the onInterceptTouchEvent of this component. If false is returned, the second method is called, that is, the dispatchTouchEvent method of the child component. If true is returned, the onTouchEvent method of the child component is called directly.

2. If you need to pass events to the child component in step 1. If the call of the sub-component's dispatchTouchEvent recursively returns false, the onTouchEvent method of this component is called. If the return value is true, the onTouchEvent method of this component does not need to be called.

3. Return the returned value of the dispatchTouchEvent to the dispatchTouchEvent method of the parent component based on the execution results of the previous two steps.


The dispatchTouchEvent in the view directly calls its own onTouchEvent.



Generally, there is no need to override the dispatchTouchEvent method. If you must rewrite the method, call the super. dispatchTouchEvent () method. Otherwise, recursive calls will stop.

Without dispatchTouchEvent, the simple execution process is as follows:

The top-level component first responds to the event and then continuously transmits the event to the child component. It calls the onInterceptTouchEvent method of the child component until the onInterceptTouchEvent method of A certain component A returns true or reaches the view component, then, the onTouchEvent method of the component is called, And the onTouchEvent method of the parent component is continuously returned to the parent component until the onTouchEvent method of a parent component returns true.

In fact, it is the process of constantly calling onInterceptTouchEvent from the parent component and then calling onTouchEvent from the child component.

Note the following:

1. If a component intercepts and processes the ACTION_DOWN event in this process, other events such as ACTION_MOVE and ACTION_UP will no longer be transmitted to its child components, instead, the returned process is executed after being passed to the component.

2. If the onInterceptTouchEvent of a component returns true to ACTION_DOWN, the subsequent ACTION_MOVE, ACTION_DOWN, and so on will not execute this onInterceptTouchEvent, but will be passed directly to the onTouchEvent of this component, however, it still goes through the onInterceptTouchEvent of its parent component.


In the process of seeing an article on the dispatchTouchEvent code for a comment, you can be more clear about the problem, the specific as follows, reference address: http://blog.csdn.net/hdxiaoyu2/article/details/25563453

@ Override public boolean dispatchTouchEvent (MotionEvent ev) {if (mInputEventConsistencyVerifier! = Null) {mInputEventConsistencyVerifier. onTouchEvent (ev, 1);} // Check for interception. final boolean intercepted; // The flag variable if (actionMasked = MotionEvent. ACTION_DOWN | mFirstTouchTarget! = Null) {final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT )! = 0; if (! DisallowIntercept) {// call your onInterceptTochEvent to determine whether intercepted = onInterceptTochEvent (ev); ev. setAction (action); // restore action in case it was changed} else {intercepted = false ;}} else {// There are no touch targets and this action is not an initial down // so this view group continues to intercept touches. intercepted = true;} // if no if (! Canceled &&! Intercepted) {if (actionMasked = MotionEvent. ACTION_DOWN | (split & actionMasked = MotionEvent. ACTION_POINTER_DOWN) | actionMasked = MotionEvent. ACTION_HOVER_MOVE) {if (newTouchTarget = null & childrenCount! = 0) {final float x = ev. getX (actionIndex); final float y = ev. getY (actionIndex); // Find a child that can receive the event. // Scan children from front to back. final View [] children = mChildren; final boolean customOrder = isChildrenDrawingOrderEnabled (); // traverses all the child views and calls their event Distribution Method dispatchTouchEvent () for (int I = childrenCount-1; I> = 0; I --) {final int childIndex = customOrder? GetChildDrawingOrder (childrenCount, I): I; final View child = children [childIndex]; if (! CanViewReceivePointerEvents (child) |! IsTransformedTouchPointInView (x, y, child, null) {continue;} newTouchTarget = getTouchTarget (child); // newTouchTarget indicates the View Target passed by the event. If it is not empty, directly jump out of the loop if (newTouchTarget! = Null) {newTouchTarget. pointerIdBits | = idBitsToAssign; break;} resetCancelNextUpFlag (child); // recursively call the subview event distribution method. if (dispatchTransformedTouchEvent (ev, false, child, idBitsToAssign )) {mLastTouchDownTime = ev. getDownTime (); mLastTouchDownIndex = childIndex; mLastTouchDownX = ev. getX (); mLastTouchDownY = ev. getY (); // set the distribution Target newTouchTarget to the current View newTouchTarget = addTouchTarget (child, idBitsToAssign ); // Mark the distribution result of the sub-View. If it is True, the following code will not call the onTouch method of the current View, that is, the reason why rule 1 is generated. alreadyDispatchedToNewTouchTarget = true; break ;}}}} if (mFirstTouchTarget = null) {// No touch targets so treat this as an ordinary view. handled = dispatchTransformedTouchEvent (ev, canceled, null, TouchTarget. ALL_POINTER_IDS);} else {// Dispatch to touch targets, excluding the new touch target if we already // dispatched To it. Cancel touch targets if necessary. TouchTarget predecessor = null; TouchTarget target = mFirstTouchTarget; while (target! = Null) {final TouchTarget next = target. next; // if the token is set to True, the following dispatchTransformedTouchEvent // alreadyDispatchedToNewTouchTarget is determined by the onTouch return value of the subview. if (token & target = newTouchTarget) {handled = true;} else {final boolean cancelChild = resetCancelNextUpFlag (target. child) | intercepted; // executes its own Touch event, if (dispatchTransformedTouchEvent (ev, cancelChild, target. child, target. pointerIdBits) {handled = true;} if (cancelChild) {if (predecessor = null) {mFirstTouchTarget = next;} else {predecessor. next = next;} target. recycle (); target = next; continue ;}} predecessor = target; target = next ;}}}

In addition, the two articles will be good and can be used as a reference:

Http://www.infoq.com/cn/articles/android-event-delivery-mechanism

Http://blog.csdn.net/hdxiaoyu2/article/details/25563453


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.