Android -- View, ViewGroup event (Touch event) processing mechanism Summary, androidviewgroup

Source: Internet
Author: User

Android -- View, ViewGroup event (Touch event) processing mechanism Summary, androidviewgroup
Events in Android

Touch event, four statuses:

ACTION_DOWN --> indicates that an event starts from ACTION_DOWN when the screen is pressed.
ACTION_MOVE --> indicates a mobile gesture.
ACTION_UP --> indicates leaving the screen
ACTION_CANCEL --> indicates canceling a gesture, which is generally generated by a program and not by the user.

One ACTION_DOWN, n ACTION_MOVE, and one ACTION_UP constitute many events in Android.

Events such as onClick, onScroll, and onFling in Android are composed of multiple Touch types.

One principle is that all touch events are passed down from the parent container, In the U shape.


Core code of View event processing mechanism

In Android, controls such as ImageView, textView, And Button do not overwrite the View's dispatchTouchEvent method. Therefore, the View event processing mechanism is effective for these controls.


View. java (based on android2.3.3 ):

Public boolean dispatchTouchEvent (MotionEvent event) {// returns true, indicating that all events are digested in the View. False is returned, indicating that only the ACTION_DOWN event is processed in the View. The event continues to be passed to the parent View (ViewGroup .... If (li! = Null & li. mOnTouchListener! = Null & (mViewFlags & ENABLED_MASK) = ENABLED & li. mOnTouchListener. onTouch (this, event) {// The onTouch method here is the onTouch () method returned true when we register the OnTouchListener callback;} if (onTouchEvent (event )) {// onTouchEvent refer to the following source code return true ;}...}


Public boolean onTouchEvent (MotionEvent event ){... // The current onTouch component must be CLICKABLE, such as Button and ImageButton. Here, CLICKABLE is true to enter the if method and return true. // If ImageView and TexitView are non-CLICKABLE views by default, CLICKABLE is false, and false is returned. Of course, there will be special cases. if the onClick listener is set for these views, CLICKABLE will also be true here. refer to the following source code if (viewFlags & CLICKABLE) = CLICKABLE | (viewFlags & LONG_CLICKABLE) = LONG_CLICKABLE) {switch (event. getAction () {case MotionEvent. ACTION_UP :... if (! Post (mPerformClick) {upload mclick (); // actually calls back The onClick () method in the OnClickListener we registered. The source code below }... break; case MotionEvent. ACTION_DOWN :... break; case MotionEvent. ACTION_CANCEL :... break; case MotionEvent. ACTION_MOVE :... break;} return true;} return false ;}


    public void setOnClickListener(OnClickListener l) {        if (!isClickable()) {            setClickable(true);        }        getListenerInfo().mOnClickListener = l;    }


    public boolean performClick() {        ...        if (li != null && li.mOnClickListener != null) {            ...            li.mOnClickListener.onClick(this);            return true;        }        return false;    }


Summary:

Only the onTouch () method that we override when registering the OnTouchListener returns false --> executes the onTouchEvent Method --> causes the onClick () callback method to be executed.

The onTouch () method returns true --> the onTouchEvent method is not executed --> The onClick () callback method is not executed.


Core code of ViewGroup Event Processing Mechanism

In Android, the Five layout controls, such as LinearLayout, are inherited from ViewGroup and ViewGroup itself is inherited from View. Therefore, the event processing mechanism of ViewGroup is effective for these controls.


ViewGroup. java (based on android2.3.3 ):

@ Overridepublic boolean dispatchTouchEvent (MotionEvent ev) {... if (action = MotionEvent. ACTION_DOWN) {if (mMotionTarget! = Null) {mMotionTarget = null;} // The onInterceptTouchEvent returns false, indicating that if (disallowIntercept |! OnInterceptTouchEvent (ev )){... // The pseudocode is as follows: // 1. Locate the current control subcontrol // 2 and determine the coordinates of the current touch point (x, y) in the rectangle of the Child control, determine whether the child control is a subclass object of viewgroup or a subclass object of view. // 3.1 if it is a subclass of viewgroup: call the dispatchTouchEvent method, and perform the preceding operation again. // 3.2 view tries to let the current view handle this event (true, the dispatchTouchEvent method ends, and returns true false, dispatchTouchEvent continues to be executed )...}}... target = mMotionTarget // target must be nullif (target = null ){... // call the method of event handling of the parent View of the current viewgroup return super. dispatchTouchEvent (ev );}...}


Public boolean onInterceptTouchEvent (MotionEvent ev) {return false; // false is returned by default}


Summary:

1. dispatchTouchEvent: determines whether the event is intercepted and handled by onInterceptTouchEvent.

When super. dispatchTouchEvent is returned, onInterceptTouchEvent determines the event flow.
When false is returned, the event will continue to be distributed and only ACTION_DOWN is processed internally.
If true is returned, the event will not be distributed and all events (ACTION_DOWN, ACTION_MOVE, ACTION_UP) are processed internally)


2. onInterceptTouchEvent: intercept an event to determine whether the event is transmitted to the subview.

If true is returned, it is intercepted and handed over to its onTouchEvent for processing.
If false is returned, it is intercepted and handed over to the subview for processing.


3. onTouchEvent: The event will eventually reach this method.

When true is returned, all events are processed internally. In other words, subsequent events will be passed to the onTouchEvent () processing of the view.
When false is returned, the event is passed up and accepted by onToucEvent. If the onTouchEvent in the top View also returns false, the event will disappear.


Comprehensive Case Analysis

From: http://www.longdw.com/android-onintercepttouchevent-ontouchevent/

Source code:

public class MainActivity extends Activity {Group1 group1;Group2 group2;MyTextView myTv;/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//--group1//----|//-------group2//---------|//------------myTvgroup1 = new Group1(this);group2 = new Group2(this);myTv = new MyTextView(this);group2.addView(myTv, new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));group1.addView(group2, new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));setContentView(group1);}}


Public class Group1 extends FrameLayout {public Group1 (Context context) {super (context); // TODO Auto-generated constructor stub} @ Overridepublic boolean onInterceptTouchEvent (MotionEvent ev) {// TODO Auto-generated method stubLog. d (Constant. LOGCAT, "Group1 onInterceptTouchEvent trigger event:" + Constant. getActionTAG (ev. getAction (); return false ;}@ Overridepublic boolean onTouchEvent (MotionEvent event) {// TODO Auto-generated method stubLog. d (Constant. LOGCAT, "Group1 onTouchEvent trigger event:" + Constant. getActionTAG (event. getAction (); return false ;}}


Public class Group2 extends FrameLayout {public Group2 (Context context) {super (context); // TODO Auto-generated constructor stub} @ Overridepublic boolean onInterceptTouchEvent (MotionEvent ev) {// TODO Auto-generated method stubLog. d (Constant. LOGCAT, "Group2 onInterceptTouchEvent trigger event:" + Constant. getActionTAG (ev. getAction (); return false ;}@ Overridepublic boolean onTouchEvent (MotionEvent event) {// TODO Auto-generated method stubLog. d (Constant. LOGCAT, "Group2 onTouchEvent trigger event:" + Constant. getActionTAG (event. getAction (); return false ;}}


Public class MyTextView extends TextView {public MyTextView (Context context) {super (context); this. setGravity (Gravity. CENTER); this. setText ("Click me! "); // TODO Auto-generated constructor stub} @ Overridepublic boolean onTouchEvent (MotionEvent event) {// TODO Auto-generated method stubLog. d (Constant. LOGCAT, "MyTextView onTouchEvent trigger event:" + Constant. getActionTAG (event. getAction (); return false ;}}


public class Constant {public static final String LOGCAT = "logcat";public static String getActionTAG(int action) {switch (action) {case 0:return "ACTION_DOWN";case 1:return "ACTION_UP";case 2:return "ACTION_MOVE";default:return "NULL";}}}

Override the onInterceptTouchEvent and onTouchEvent methods of Group1 and Group2 respectively, and override the onTouchEvent method of MyTextView. The final control hierarchy is as follows:


1. logcat output in the default return value is as follows:

After the test, we can see that the result is the same as that returned by all methods by default. The capture sequence of the down event is onInterceptTouchEvent before onTouchEvent. Because the onTouchEvent returned value is false, the down event is not digested, subsequent move and up events do not appear, And the onTouchEvent method of the parent control is returned in reverse order to capture the event, as shown in:


2. If the returned value of all ontouchevents is true, the logcat output is as follows:


The output result shows that the child control MyTextView has digested the down event, and the subsequent move and up events are captured normally. Because the down event is digested, The onTouchEvent method on the upper layer is not executed, as shown in: (the three arrows indicate the down, move, and up events respectively)


In this case, if the onTouchEvent method in MyTextView returns false, and the onTouchEvent methods of group1 and group2 naturally return true results in the same order:

The test output proves the order of prediction:

Note:Some people may be confused about this situation. ACTION_DOWN is understandable, but why does ACTION_MOVE not experience myTv? Besides, ACTION_MOVE only experiences onInterceptTouchEvent of group1 and onTouchEvent of group2, but not onInterceptTouchEvent of group2? I was puzzled at the beginning. Later I thought about it. We compared 1st items. Because onTouchEvent returned false, and the down event was not consumed, the subsequent move and up events did not appear, the same is true here because the onTouchEvent in myTv returns false, that is, the down event is not consumed, so the move and up events will not be in this view, but group2 intercepts the down event, but why did the onInterceptTouchEvent in group2 fail to be executed in later moves? Do not forget the original intention of onInterceptTouchEvent. If false is returned, it is processed by its subview or viewgroup class, while the sub-Control of group2 is obviously myTv and the onTouchEvent of myTv returns false, that is, the subsequent move and up events cannot be received, in this case, it is not necessary to continue the distribution through onInterceptTouchEvent (because the distribution is still not received ). The onTouchEvent of 2 intercepts the event and consumes the event because it returns true.


3. If the value of the onInterceptTouchEvent method returned by a GroupView is true, the logcat output is as follows (such as group2 ):

If true is returned in the return value of this method, the Child control will not get any Click Event and forward it to its onTouchEvent method, as shown in:

If the value returned by the onTouchEvent method is true, the trigger is triggered in sequence according to the regular result:

Finally, the results of logcat confirm this guess:


There is also a good article, can be used as a supplement to this case, http://orgcent.com/android-touch-event-mechanism/


Zookeeper

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.