Android Event Distribution

Source: Internet
Author: User
Tags gety

    • 1. Overview
      Clicking on a control first invokes the activity's Dispatchtouchevent method and passes through the window to the layout that Decorview eventually passes to us, and if the event is not intercepted, Find the corresponding control that was clicked in the Dispatchtouchevent method of the layout, and then call the control's Dispatchtouchevent method, The Dispatchtouchevent method determines whether the Ontouchevent method is called based on the return value of the Ontouch method, and the Ontouchevent method determines whether the OnClick method is executed based on Onclicklistener If the Intercept event calls ViewGroup's Ontouchevent method directly. If a view's Ontouchevent returns false, the ontouchevent of its parent container will be called and will eventually be passed to the activity handler.
      ViewGroup Pseudo Code:

      public boolean dispatchtouchevent (Motionevent ev) {
      Boolean result = false;
      if (onintercepttouchevent (EV)) {
      result = ontouchevent (EV);
      }else{
      result = child.dispatchtouchevent (EV);
      }
      return result;

}

    • 2. Source Code Analysis

Dispatchtouchevent method of view

   public boolean dispatchtouchevent (Motionevent event) {//If the event should is handled by accessibility focus Firs T. if (Event.istargetaccessibilityfocus ()) {//We don't have the focus or no virtual descendant has it, does not hand        Le the event.        if (!isaccessibilityfocusedvieworhost ()) {return false;        }//We have a focus and got the event, then use Normal event dispatch.    Event.settargetaccessibilityfocus (FALSE);    } Boolean result = false;    if (minputeventconsistencyverifier! = null) {minputeventconsistencyverifier.ontouchevent (event, 0);    } final int actionmasked = event.getactionmasked ();    if (actionmasked = = Motionevent.action_down) {//Defensive cleanup for new gesture stopnestedscroll (); } ******if (Onfiltertoucheventforsecurity (event)) {//noinspection simplifiableifstatement listenerinfo l        i = Mlistenerinfo;        if (Li! = null && Li.montouchlistener! = null        && (Mviewflags & enabled_mask) = = ENABLED && Li.mOnTouchListener.onTouch (This,        Event)) {result = true;        } if (!result && ontouchevent (event)) {result = true; }}****** if (!result && minputeventconsistencyverifier! = null) {Minputeventconsistencyverifier.onu    Nhandledevent (event, 0);    }//Nested scrolls if this is the end of a gesture;    Also cancel it if we tried an action_down but we didn ' t want the rest//of the gesture.            if (actionmasked = = Motionevent.action_up | |            actionmasked = = Motionevent.action_cancel | | (actionmasked = = Motionevent.action_down &&!result))    {Stopnestedscroll (); } return result;

In the Onfiltertoucheventforsecurity (event) method, first determine whether Ontouchlistener is empty ("public void Setontouchlistener (Ontouchlistener l ) {
Getlistenerinfo (). Montouchlistener = l;
} "), then determine if the current control is enabled, then the Ontouch method is judged, and if True does not execute the next Ontouchevent method, the Ontouchevent method is executed for false

Ontouchevent method of view:

     PublicBooleanontouchevent(motioneventEvent) {Finalfloatx =Event. GetX (); Finalfloaty =Event. GetY (); FinalintViewFlags = Mviewflags; FinalintAction =Event. Getaction ();if((ViewFlags & enabled_mask) = = DISABLED) {if(Action = = motionevent.action_up && (mprivateflags & pflag_pressed)! =0) {setpressed (false); }//A disabled view that's clickable still consumes the touch            //events, it just doesn ' t respond to them.            return((viewflags & clickable) = = Clickable | | (ViewFlags & long_clickable) = = long_clickable) | |        (ViewFlags & context_clickable) = = context_clickable); }if(Mtouchdelegate! =NULL) {if(Mtouchdelegate.ontouchevent (Event)) {return true; }        }if((viewflags & clickable) = = Clickable | |                (ViewFlags & long_clickable) = = long_clickable) | | (ViewFlags & context_clickable) = = context_clickable) {Switch(action) { CaseMotionEvent.ACTION_UP:boolean prepressed = (mprivateflags & pflag_prepressed)! =0;if((Mprivateflags & pflag_pressed)! =0|| prepressed) {//Take focus if we don't have an it already and we should in                        //Touch mode.Boolean Focustaken =false;if(Isfocusable () && isfocusableintouchmode () &&!isfocused ())                        {Focustaken = Requestfocus (); }if(prepressed) {//The button is being released before we actually                            //showed it as pressed. Make it show the pressed                            //state now (before scheduling the click) to ensure                            //The user sees it.Setpressed (true, x, y); }if(!mhasperformedlongpress &&!mignorenextupevent) {//This was a tap, so remove the Longpress checkRemovelongpresscallback ();//Only perform take click on actions if we were in the pressed state                            if(!focustaken) {//Use a Runnable and post this rather than calling                                //PerformClick directly. This lets other visual state                                //Of the view update before click Actions Start.***********if(Mperformclick = =NULL) {Mperformclick =NewPerformClick (); }if(!post (Mperformclick))                                {PerformClick (); }***********                            }                        }if(Munsetpressedstate = =NULL) {munsetpressedstate =NewUnsetpressedstate (); }if(prepressed) {postdelayed (munsetpressedstate, viewconfiguration.getpress                        Edstateduration ()); }Else if(!post (Munsetpressedstate)) {//If The post failed, unpress right nowMunsetpressedstate.run ();                    } removetapcallback (); } mignorenextupevent =false; Break; CaseMotionEvent.ACTION_DOWN:mHasPerformedLongPress =false;if(Performbuttonactionontouchdown (Event)) { Break; }//Walk up the hierarchy to determine if we ' re inside a scrolling container.Boolean isinscrollingcontainer = Isinscrollingcontainer ();/inside a scrolling container, delay the pressed feedback for                    //A short period in case the is a scroll.                    if(Isinscrollingcontainer) {mprivateflags |= pflag_prepressed;if(Mpendingcheckfortap = =NULL) {Mpendingcheckfortap =NewCheckfortap (); } mpendingcheckfortap.x =Event. GetX (); MPENDINGCHECKFORTAP.Y =Event. GetY ();                    Postdelayed (Mpendingcheckfortap, Viewconfiguration.gettaptimeout ()); }Else{//Not inside a scrolling container, so show the feedback right awaySetpressed (true, x, y); Checkforlongclick (0); } Break; CaseMotionEvent.ACTION_CANCEL:setPressed (false);                    Removetapcallback ();                    Removelongpresscallback (); Mincontextbuttonpress =false; Mhasperformedlongpress =false; Mignorenextupevent =false; Break; CaseMotionEvent.ACTION_MOVE:drawableHotspotChanged (x, y);//Be lenient about moving outside of buttons                    if(!pointinview (x, Y, Mtouchslop)) {//Outside buttonRemovetapcallback ();if((Mprivateflags & pflag_pressed)! =0) {//Remove Any future long Press/tap checksRemovelongpresscallback (); Setpressed (false); }                    } Break; }return true; }return false; }

In the Ontouchevent event sequence, the UP option (finger lift) executes performclick (); Let's look at the source code of PerformClick ().

 public   Boolean  performclick  () {final  boolean  result; final         Listenerinfo li = mlistenerinfo; if  (Li! = null  && li.monclicklistener! = null            ) {playsoundeffect (Soundeffectconstants.click);            Li.mOnClickListener.onClick (this );        result = true ;        } else  {result = false ;        } sendaccessibilityevent (accessibilityevent.type_view_clicked);    return  result; }

The OnClick method is executed as long as the onclicklistener is not empty, and we set the Onclicklistener in the following method

    publicvoidsetOnClickListener(@Nullable OnClickListener l) {        if (!isClickable()) {            setClickable(true);        }        getListenerInfo().mOnClickListener = l;    }

Finally, if a view's Ontouchevent returns false, the ontouchevent of its parent container will be called and will eventually be passed to the activity handler.

The Ontouchevent method of activity

  publiconTouchEventevent) {        if (mWindow.shouldCloseOnTouch(thisevent)) {            finish();            returntrue;        }        returnfalse;    }
    • 3. The same sequence of events starts with the down event and the up event ends with an indeterminate number of move events in the middle
    • 4.ViewGroup is an abstract class, the Onintercepttouchevent method returns false by default (does not intercept), the method is not in view
    • 5.View ontouchevent consumes events by default (returns True) unless not clickable (clickable and longclickable also default to False for false,longclickable)

Android Event Distribution

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.