Android--view, ViewGroup event (touch event) Processing mechanism summary

Source: Internet
Author: User

Events in Android

Touch events, four states:

Action_down--> said the screen was pressed, an event must start from Action_down
Action_move--> represents a move gesture
Action_up--> means leaving the screen
Action_cancel--> indicates that the cancellation gesture is normally generated by the program and is not generated by the user

A action_down, n action_move,1 action_up, constitutes a multitude of events in Android.

The event onclick, onscroll, onfling and so on in Android are all made up of a lot of touch.

One principle, all touch events are passed down from the parent container, in a U-shape.


View event handling mechanism core code

Controls such as ImageView, TextView, and button in Android do not override the view's Dispatchtouchevent method, so the view's event handling mechanism works for these controls.


View.java(based on android2.3.3):

    public boolean dispatchtouchevent (Motionevent event) {//Returns TRUE, indicating that the view internally digests all events. Returns false, indicating that the view internally only handles the Action_down event, the event continues to pass, and is passed to the Superior view (ViewGroup). ...            if (Li! = null && Li.montouchlistener! = null && (mviewflags & enabled_mask) = = ENABLED                    && Li.mOnTouchListener.onTouch (this, event)) {//The OnTouch method here is the callback of the OnTouch () methods that were rewritten when we registered Ontouchlistener, and                return true;            }                if (ontouchevent (event)) {//Ontouchevent refer to the following source code                return true;            }        ...    }


    public boolean ontouchevent (Motionevent event) {...//the components of the current Ontouch must be clickable, such as Button,imagebutton, and so on, here clic Kable is true before it enters the If method and finally returns true. If it is ImageView, Texitview These default is non-clickable view, here clickable to false, and finally return false.                   Of course there will be special circumstances, if you set the OnClick listener to these view, here clickable will also be true, refer to the following source if ((ViewFlags & clickable) = = Clickable | | (ViewFlags & long_clickable) = = long_clickable)) {switch (event.getaction ()) {C                                    ASE motionevent.action_up: ... if (!post (Mperformclick)) {                      PerformClick ();//The actual callback of our registered Onclicklistener in the re-onclick () method, 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;    }


Summarize:

Only we register Ontouchlistener when the overridden Ontouch () method returns False--> execution Ontouchevent method, which causes the onclick () callback method to execute

The OnTouch () method returns the True--> Ontouchevent method does not execute-causing the onclick () callback method to not execute


ViewGroup event handling mechanism core code

The five layout controls, such as LinearLayout in Android, are inherited from ViewGroup, and ViewGroup itself is inherited from view, so the ViewGroup event handling mechanism works 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;} Onintercepttouchevent returns false, stating that the pass-through//onintercepttouchevent returns True, indicating the Intercept if (disallowintercept | |! Onintercepttouchevent (EV)) {...//pseudocode as follows://1, find the current control child control//2, and determine the coordinates of the current touch point (x, y) in which child control is in the rectangular area// 3, determine whether the current child control is a subclass object of ViewGroup, or the child class object of the view//3.1  if it is a subclass of ViewGroup: Call its Dispatchtouchevent method, the above operation again//3.2  view Try to get the current view to handle this event (the             True,dispatchtouchevent method ends and returns true             False,dispatchtouchevent continues to execute down) ...}} ... target = Mmotiontarget//target must be nullif (target = = null) {...//call the method of handling events for the parent view of the current ViewGroup return Super.dispatchtouchevent (EV);}   ...   }


    public boolean onintercepttouchevent (motionevent ev) {        return false;//returns false by default    }


Summarize:

1, dispatchtouchevent role: Determine whether the event by onintercepttouchevent to intercept processing.

When returning super.dispatchtouchevent, the flow of events is determined by onintercepttouchevent.
Returns false, the event is continued to be distributed, and the Action_down is processed internally only
Returns True when the distribution event is not continued and all events are handled internally (ACTION_DOWN,ACTION_MOVE,ACTION_UP)


2, Onintercepttouchevent action: Intercept event, used to determine whether the event is transmitted to the child view

Returns true when intercepted and handed over to their own ontouchevent processing
Returns false when intercepted and handed over to the child view to handle


3. Ontouchevent Effect: The event eventually arrives at this method

Returns True when all events are handled internally, in other words, subsequent events will continue to be passed to the view's ontouchevent () processing
When False is returned, the event is passed up, accepted by Ontoucevent, and the event disappears if ontouchevent in the top view also returns false.


Comprehensive case Study

Following excerpt from: http://www.longdw.com/android-onintercepttouchevent-ontouchevent/

Source:

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 Constructo R 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 Constructo R 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";p ublic static String getactiontag (int action) {switch (action) {Case 0:return "Action_down", Case 1:return "action_up", Case 2:return "Action_move";d Efault:return "NULL";}}}

Override the Onintercepttouchevent and Ontouchevent methods of Group1 and Group2, override Mytextview's Ontouchevent method, and finally get the following hierarchy of controls:


1. In the case of the default return value, the Logcat output is as follows:

after testing, it is known that by default and all methods return a value of false the result is consistent, the capture order of the down event onintercepttouchevent precedes Ontouchevent, because the Ontouchevent return value is False, The down event is not digested, the subsequent move and up events do not appear, and the reverse order is returned to the parent control's Ontouchevent method to capture, as shown in:


2. For all ontouchevent return values of true, the Logcat output is as follows:


The output shows that the child controls Mytextview Digest the down event, and the subsequent move and up events are properly captured, as the down event is digested and the upper Ontouchevent method is not executed as shown in: (three arrows refer to down, move , up events)


In this case, if the Ontouchevent method in Mytextview returns to false, and the Ontouchevent method of Group1 and Group2 returns True, the result is naturally the order:

The test output proves this sequence of guesses:

Note: Some people may be more puzzled about this situation, action_down good understanding, but action_move why not experience MyTV, and Action_move only experienced group1 onintercepttouchevent And Group2 's ontouchevent without experiencing group2 's onintercepttouchevent? I began to understand, and then think about it also, we compare 1th, because Ontouchevent returned false and did not consume the down event resulting in the subsequent move and up did not appear, It's the same here. Because Ontouchevent returns false in MyTV, which means that there is no consumption of the down event, then the move and up will not be in the view, but Group2 intercepted the down event, But later move why Group2 in the onintercepttouchevent did not carry out, reason everybody don't forget Onintercepttouchevent's original intention is what, Returning false is to have its child view or ViewGroup class processed, while Group2 's child control is obviously MyTV and MyTV's ontouchevent returns false, which means that no subsequent move and up events are received. There is no need to go through the onintercepttouchevent to continue distributing (because the distribution is still not received), after the group2 ontouchevent because it returns true, intercepts the event and consumes the event.


3. When the Onintercepttouchevent method in a Groupview returns a value of true, the Logcat output is as follows (for example, group2):

If True is returned in the return value of the method, the child control will not get any click events, instead forwarding to its own Ontouchevent method, as shown in:

If the return value of the Ontouchevent method is true, then the rule results are triggered as sequential:

The result of the final logcat confirms this speculation:


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




Android--view, ViewGroup event (touch event) Processing mechanism summary

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.