Deeply parsing the event-passing _java of view in Andoird application development

Source: Internet
Author: User
Tags gety

The following is an example of an event passed after a view is clicked.
First, analyze the Dispatchtouchevent () method in view, which is the first way to click View Execution.

public boolean dispatchtouchevent (Motionevent event) {
 if montouchlistener!= null && (Mviewflags & Enab Led_mask = = ENABLED &&
   montouchlistener.ontouch (this, event)) {return
   true;
 }
 Return Ontouchevent (event);
}

Note: The inside contains two callback functions Ontouch (), Ontouchevent (), and if the control is bound Ontouchlistener and the control is enabled, then the Ontouch () method is executed, if the method returns True, It means that the touch event has been consumed by the Ontouchlistener listener and will not be distributed again, but if false, it is not consumed and continues to be distributed to the control's ontouchevent () for processing.

The Ontouchevent () method is then analyzed for further touch event processing.

if ((viewflags & clickable) = = Clickable | | 
   (ViewFlags & long_clickable) = = long_clickable)) { 
  switch (event.getaction ()) {case 
   motionevent.action_up :
    ..... 
      PerformClick (); Response Click event Break 
    ; 
   Case Motionevent.action_down: ... break 
   ; 
   Case Motionevent.action_cancel: ... break 
   ; 
   Case Motionevent.action_move: ... break 
   ; 
  return true; 
} 
return false;

If the control is clickable, long_clickable, you can respond to the corresponding event and return True after the response is complete. For example, click on the event, first respond to Action_down, then break and return true, then hand up, and from Dispatchtouchevent () distributed, and then respond to ACTION_UP, which will go PerformClick () response to the Click event.

Responding to click events

public boolean PerformClick () {
  sendaccessibilityevent (accessibilityevent.type_view_clicked);
  if (Monclicklistener!= null) {
     playsoundeffect (soundeffectconstants.click);
     Monclicklistener.onclick (this);
     return true;
  }
  return false;
}

Inside executes Monclicklistener.onclick (this), the OnClick () function that backs up the binding listener.

Key points:
What is the difference between Ontouch and ontouchevent and how to use it?
For:
When the view control accepts a touch event, if the control is bound to the Ontouchlistener listener and the control is enable, then the Ontouch () method is executed, and if true, the touch event is consumed, no longer passed down, and if false, Then continue to invoke the Ontouchevent () event.

After the Android touch event is passed to the Decorview (a framelayout) at the top of the activity, it passes through the ViewGroup layer to the view tree and eventually passes the event to the view that is actually received. Some important methods are given below.

Dispatchtouchevent
when an event is passed to a viewgroup, the dispatchtouchevent is invoked. Code is truncated

public boolean dispatchtouchevent (Motionevent ev) {Boolean handled = false;
    if (onfiltertoucheventforsecurity (EV)) {final int action = Ev.getaction ();

    Final int actionmasked = action & motionevent.action_mask;
      Attention 1: Purge some states if (actionmasked = = Motionevent.action_down) {cancelandcleartouchtargets (EV) at press time;
    Note that this method resettouchstate ();
    }//Attention 2: Check to see if final Boolean intercepted is to be intercepted; If you have just pressed or already have a child view to process the IF (actionmasked = Motionevent.action_down | | | mfirsttouchtarget!= NULL) {FINA
      L Boolean disallowintercept = (Mgroupflags & flag_disallow_intercept)!= 0;
        if (!disallowintercept) {intercepted = Onintercepttouchevent (EV); Ev.setaction (action);
      Restore action in case it is changed} else {intercepted = false;
    } else {//is not the beginning of an action sequence and does not have a child view to handle it, directly intercepting intercepted = true;
//The event is not canceled and is not intercepted by the current viewgroup to find out if there is a child view    if (!canceled &&!intercepted) {//If this is the beginning of a series of actions or if there is a new pointer press we need to find a child view that can handle this pointer if (a ctionmasked = = Motionevent.action_down | | (Split && actionmasked = Motionevent.action_pointer_down) | | 

        actionmasked = = motionevent.action_hover_move) {final int actionindex = Ev.getactionindex ();//Always 0 for down The limit on the touch point 32 above is that this leads to final int idbitstoassign = split?

        1 << Ev.getpointerid (actionindex): Touchtarget.all_pointer_ids;
        Final int childrencount = Mchildrencount;
          if (Newtouchtarget = = null && childrencount!= 0) {final float x = Ev.getx (Actionindex);

          Final float y = ev.gety (Actionindex);
          Sort all the child View of the current viewgroup, put at the top of the beginning final arraylist<view> preorderedlist = Buildorderedchildlist ();
      Final Boolean customorder = Preorderedlist = = null && ischildrendrawingorderenabled ();    Final view[] children = Mchildren; for (int i = childrenCount-1 i >= 0; i--) {final int childindex = Customorder? getchil
            Ddrawingorder (Childrencount, i): i; Final View child = (preorderedlist = null)?

               Children[childindex]: Preorderedlist.get (Childindex);
            Canviewreceivepointerevents visible view can accept events//Istransformedtouchpointinview calculate whether it falls on the click Area
              if (!canviewreceivepointerevents (child) | |!istransformedtouchpointinview (x, y, child, null)) {
              Ev.settargetaccessibilityfocus (FALSE);
            Continue
            //Be able to handle this pointer view has been processed before the pointer, then put newtouchtarget = Gettouchtarget (child);
              if (newtouchtarget!= null) {//child be already receiving touch within its bounds.
              Give it the new pointer in addition to the ones it is handling. NewtouChtarget.pointeridbits |= idbitstoassign;
            Break }//attention 3: Send directly to the child view if (Dispatchtransformedtouchevent (EV, FALSE, children, IdB
              Itstoassign)) {//wants to receive touch within its bounds.
              Mlasttouchdowntime = Ev.getdowntime ();
                if (preorderedlist!= null) {//Childindex points into presorted list, find original index
                    for (int j = 0; J < Childrencount J + +) {if (children[childindex] = = Mchildren[j]) {
                    Mlasttouchdownindex = j;
                  Break
              }} else {mlasttouchdownindex = Childindex;
              } Mlasttouchdownx = Ev.getx ();
              Mlasttouchdowny = Ev.gety ();
              Newtouchtarget = Addtouchtarget (Child, idbitstoassign);
             Alreadydispatchedtonewtouchtarget = true; Break A child view of the receive event has been found before, and if NULL indicates that there is no child view to take over, the current viewgroup needs to process the IF (Mfirsttouc Htarget = = null) {//ViewGroup processing handled = dispatchtransformedtouchevent (EV, canceled, NULL, Toucht Arget.
    All_pointer_ids); } else {if (alreadydispatchedtonewtouchtarget) {//ignore Some code if (Dispatchtran
         Sformedtouchevent (EV, Cancelchild, Target.child, target.pointeridbits)) {handled = true;
}} return handled;

 }

The attention in the code above will be covered in the following section, with a focus on attention.

One thing to point out here is that different pointer in a series of actions can be assigned to different view responses. ViewGroup maintains a list of pointerid and processing view Touchtarget, a touchtarget represents a child view that can handle pointer, and of course a view can handle multiple pointer, For example, two fingers are in one of the child view areas. Inside the touchtarget, an int is used to store the pointerid that it can handle, a int32 bit, which is why the upper layer can only allow up to 32 points of touch at the same time.

Take a look at attention 3 code, we often say that the view dispatchtouchevent if return false, then it can not series actions behind the action, this is why? Because attention 3 returns false, it is not recorded in Touchtarget, and ViewGroup thinks you are incapable of handling this event.

Here you can see that viewgroup really handled the event in the Dispatchtransformedtouchevent, and followed it in to see:

Dispatchtransformedtouchevent
Private Boolean dispatchtransformedtouchevent (Motionevent event, Boolean cancel,
    View Child, int desiredpointeridbits) {

   ///No subclass processing, then give viewgroup processing
  if (child = = null) {
    handled = super.dispatchtouchevent (transformedevent);
  } else {
    final float OffsetX = mscrollx-child.mleft;
    Final float OffsetY = mscrolly-child.mtop;
    Transformedevent.offsetlocation (OffsetX, OffsetY);
    if (! Child.hasidentitymatrix ()) {
      transformedevent.transform (Child.getinversematrix ());
    }

    handled = Child.dispatchtouchevent (transformedevent);
  }
  return handled;
}

You can see here, anyway, that the dispatchtouchevent of view will be invoked, which is the place to really handle this one click event.

Dispatchtouchevent Public
  Boolean dispatchtouchevent (Motionevent event) {
    if (onfiltertoucheventforsecurity (event)) {
    ///GO first to the View Ontouch event, if Ontouch returns True
    listenerinfo li = mlistenerinfo;
    if (Li!= null && li.montouchlistener!= null
        && (mviewflags & enabled_mask) = = ENABLED
        && Amp Li.mOnTouchListener.onTouch (this, event)) {result
      = true;
    }

    if (!result && ontouchevent (event) {result
      = true;
    }
  }
    return result;
  }

The Ontouch event we set to the view is at a higher priority, and if Ontouch execution returns True, then the view ontouchevent is not taken, and some of our click events are handled in Ontouchevent. This is why the click-related events that return True,view in Ontouch are not processed.

a little summary of this process
ViewGroup when receiving an event from a superior, if it is the beginning of a series of touch events (Action_down), ViewGroup will first see if you need to intercept this event (the default implementation of Onintercepttouchevent,viewgroup returns false directly to Not intercept), and then ViewGroup iterate through all of their view. Locate the view that is currently clicked, and immediately call the dispatchtouchevent of the target view. If the target view's dispatchtouchevent returns false, the target view is only in that position, it does not want to accept the event, just want to do a quiet view (I silently watch you pretend *). At this time, ViewGroup will also go to walk himself dispatchtouchevent,done!

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.