Android Source code parsing (21)-->popupwindow loading drawing process

Source: Internet
Author: User

In the previous articles we analyzed the activity and dialog loading drawing process, cancel the drawing process, I believe you have a perceptual understanding of the Windows drawing mechanism of the Android system, this article we will continue to analyze the Popupwindow loading drawing process.

Before we analyze Popupwindow, we will first say what is Popupwindow? The best way to understand a class is to look at the definition of this class, and here we summarize the description of the Popupwindow class in the Android system:

A Popup window that can is used to the display an arbitrary view. The popup window is a floating container this appears on top of the current
Activity.

A popupwindow can be used to show that any view,popupwindow is a hover that is easy to display on top of the current activity.
Simply put, Popupwindow is a window that hovers over the activity and can be used to show any layout file.

Before we explain the loading drawing mechanism of Popupwindow, let's write a simple example to illustrate the simple usage of Popupwindow.

public static View Showpopupwindowmenu (Activity mcontext, view anchorview, int layoutid) {Layoutinflater inflater = (Layoutinflater) mcontext. Getsystemservice(Context. LAYOUT_inflater_service);View view = Inflater. Inflate(LayoutID, NULL);Popupwindow = new Popupwindow (view, Displayutil. Dip2PX (Mcontext,148), WindowManager. Layoutparams. WRAP_content);Popupwindow. Setbackgrounddrawable(Mcontext. Getresources(). Getdrawable(R. drawable. Menu_BG));Popupwindow. Setfocusable(true);Popupwindow. Setoutsidetouchable(true);int[] location = new int[2];Anchorview. Getlocationonscreen(location);Popupwindow. Setanimationstyle(R. Style. Popwin_anim_style);Popupwindow. Showatlocation(Anchorview, Gravity. NO_gravity, location[0]-Popupwindow. GetWidth() + Anchorview. GetWidth()-Displayutil. Dip2PX (Mcontext, A), location[1] + Anchorview. GetHeight()-Displayutil. Dip2PX (Mcontext,Ten));Popupwindow. Setondismisslistener(New Popupwindow. Ondismisslistener() {@Override public void Ondismiss () {Popupwindow = null;}        });Return view;}

You can see that we first resolve the layout file to the in-memory view object through the Layoutinflater object, and then create a Popupwindow object, and you can see that three parameters are passed, one is the view object, and the other is the width and height of the Popupwindow.

Here is the beginning of the Popupwindow initialization process, OK, let's take a look at the implementation of the Popupwindow construction method:

publicPopupWindowintint height) {        thisfalse);    }

You can see that the overloaded construction method of Popupwindow is called here, so let's continue to look at the implementation logic of this overloaded construction method:

public   Popupwindow  (View contentview, int  width, int  height, boolean  focusable) {if  (Conten            TView! = null ) {mcontext = Contentview.getcontext ();        Mwindowmanager = (WindowManager) mcontext.getsystemservice (Context.window_service);        } setcontentview (Contentview);        SetWidth (width);        SetHeight (height);    Setfocusable (focusable); }

Here first, according to whether the incoming view is empty to make a judgment, if not empty, then initialize the member variables, context and Mwindowmanager, you can find the Mcontext object here is the incoming view component of the reserved context object, The Mwindowmanager here is the service local interface that is registered when the application process is created. The Setcontentview method is then called, and this is the assignment for the contentview of the Popupwindow. The SetWidth, SetHeight, and setfocusable methods that are called later are assigned to the Popupwindow member variables, width,height,focusable, and so on, so that the Popupwindow construction method executes.

We go back to our example code and in the following code we call: Popupwindow.setbackgrounddrawable, popupwindow.setfocusable, Popupwindow.setoutsidetouchable,
Popupwindow.setanimationstyle and other methods, initialize the relevant member variables in the Popupwindow, and finally we call the Popupwindow.showatlocation method to show Popupwindow, here we specifically look at show The implementation logic of Atlocation:

publicvoidshowAtLocationintintint y) {        showAtLocation(parent.getWindowToken(), gravity, x, y);    }

As you can see, the overloaded functions of showatlocation are called, so we continue to look at how this overloaded function is implemented:

 Public void showatlocation(IBinder token,intGravityintXintY) {if(isshowing () | | mcontentview = =NULL) {return;        } transitionmanager.endtransitions (Mdecorview);        Unregisterforscrollchanged (); Misshowing =true; Misdropdown =false;FinalWindowmanager.layoutparams p = createpopuplayoutparams (token); Preparepopup (P);//Only override the default if some gravity is specified.        if(Gravity! = gravity.no_gravity)        {p.gravity = gravity;        } p.x = x;        P.y = y;    Invokepopup (P); }

You can see that by calling the Createpopuplayoutparams method to create the Windowmanager.layoutparams object, and then calling the Preparepopup method, you can look at the specific implementation of the Preparepopup method:

Private void Preparepopup(Windowmanager.layoutparams p) {if(Mcontentview = =NULL|| Mcontext = =NULL|| Mwindowmanager = =NULL) {Throw NewIllegalStateException ("must specify a valid content view by"+"Calling Setcontentview () before attempting to show the popup."); }//The old decor view is transitioning out. Make sure it finishes        //And cleans up before we try to create another one.        if(Mdecorview! =NULL) {mdecorview.canceltransitions (); }//When a background is available, we embed the content view within        //Another view that owns the background drawable.        if(Mbackground! =NULL) {Mbackgroundview = Createbackgroundview (Mcontentview);        Mbackgroundview.setbackground (Mbackground); }Else{Mbackgroundview = Mcontentview; } Mdecorview = Createdecorview (Mbackgroundview);//The background owner should is elevated so it casts a shadow.Mbackgroundview.setelevation (melevation);//We may wrap this in another view, so We'll need to manually specify        //the surface insets.FinalintSurfaceinset = (int) Math.ceil (Mbackgroundview.getz () *2); P.surfaceinsets.Set(Surfaceinset, Surfaceinset, Surfaceinset, Surfaceinset); P.hasmanualsurfaceinsets =true; mpopupviewinitiallayoutdirectioninherited = (mcontentview.getrawlayoutdirection () = = View.LAYOUT_DIRECTION_        INHERIT);        Mpopupwidth = P.width;    Mpopupheight = P.height; }

The parameters of the Preparepopup method are Windowmanager.layoutparams, and then set a few of the more important member variables in Popupwindow, first look at the Mbackgroundview initialization process:

if{            mBackgroundView = createBackgroundView(mContentView);            mBackgroundView.setBackground(mBackground);        }else{            mBackgroundView = mContentView;        }

It can be found that if we set the Mbackground variable and we execute the Popupwindow Setbackgound method at the time of initialization, then we are doing the IF, Here's a look at the specific execution logic of Createbackgourndview:

PrivatePopupbackgroundviewCreatebackgroundview(View Contentview) {FinalViewgroup.layoutparams layoutparams = Mcontentview.getlayoutparams ();Final intHeightif(Layoutparams! =NULL&& Layoutparams.height = = ViewGroup.LayoutParams.WRAP_CONTENT) {height = ViewGroup.LayoutParams.WRAP_C        ontent; }Else{height = ViewGroup.LayoutParams.MATCH_PARENT; }FinalPopupbackgroundview Backgroundview =NewPopupbackgroundview (Mcontext);FinalPopupbackgroundview.layoutparams Listparams =NewPopupbackgroundview.layoutparams (ViewGroup.LayoutParams.MATCH_PARENT, height); Backgroundview.addview (Contentview, listparams);returnBackgroundview; }

As you can see, Createbackgroundview's execution logic is to wrap a layer of popupbackgroundview in the outer layer of the parameter Contentview, And here the Popupbackgroundview value of our custom framelayout subclass, overriding its Oncreatedrawablestate method.

Go back to our Preparepopup method, here we call the Createdecorview method to initialize the Mdectorview variable, we can look at the specific implementation of Createdecorview:

PrivatePopupdecorviewCreatedecorview(View Contentview) {FinalViewgroup.layoutparams layoutparams = Mcontentview.getlayoutparams ();Final intHeightif(Layoutparams! =NULL&& Layoutparams.height = = ViewGroup.LayoutParams.WRAP_CONTENT) {height = ViewGroup.LayoutParams.WRAP_C        ontent; }Else{height = ViewGroup.LayoutParams.MATCH_PARENT; }FinalPopupdecorview Decorview =NewPopupdecorview (Mcontext);        Decorview.addview (Contentview, ViewGroup.LayoutParams.MATCH_PARENT, height); Decorview.setclipchildren (false); Decorview.setcliptopadding (false);returnDecorview; }

Can be found here is also to the parameters Contentview outside wrapped a layer of popupdecorview, here Popupdecorview is also our custom Framelayout sub-class, Popupdecorview source More, Here is not all posted out, here specifically to see the implementation of its Ontouchevent method:

@Override PublicBooleanontouchevent(motioneventEvent) {Finalintx = (int)Event. GetX (); Finalinty = (int)Event. GetY ();if((Event. getaction () = = Motionevent.action_down) && ((X <0) || (x >= getwidth ()) | | (Y <0) || (Y >= getheight ()))) {Dismiss ();return true; }Else if(Event. getaction () = = Motionevent.action_outside) {dismiss ();return true; }Else{returnSuper.ontouchevent (Event); }        }

It can be found that it rewrites the ontouchevent time, so that when we click outside the Popupwindow will execute Pupopwindow dismiss method, Cancel Popupwindow.

Well, go back to our Showasdropdown method, and then call the Invokepopup method after the completion of the Preparepopup method, where the method should be to perform the loading and display logic of Popupwindow specifically. Here we take a concrete look at its implementation logic:

privatevoidinvokePopup(WindowManager.LayoutParams p) {        ifnull) {            p.packageName = mContext.getPackageName();        }        final PopupDecorView decorView = mDecorView;        decorView.setFitsSystemWindows(mLayoutInsetDecor);        setLayoutDirectionFromAnchor();        mWindowManager.addView(decorView, p);        ifnull) {            decorView.requestEnterTransition(mEnterTransition);        }    }

We see here we call the Mwindowmanager.addview method, read our previous few about dialog and activity of the loading and the actual flow of the students should know here AddView is actually our layout drawing process, here the Mwindowmanager is we in the tune When initialized with the Popupwindow constructor, the call is:

ifnullnull) {            mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);        }

And here the Mcontext.getsystemservice is an interface its specific implementation is implemented in Contextimpl, so here we look at the implementation of Contextimpl Getsystemservice:

@Override    publicgetSystemService(String name) {        return SystemServiceRegistry.getSystemService(this, name);    }

Well, the Getsystemservice method in Contextimpl calls the static method Getsystemservice in Systemserviceregister, So let's take a look at how the Systemserviceregister is implemented.

publicstaticgetSystemService(ContextImpl ctx, String name) {        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);        returnnullnull;    }

Here the discovery of the service object is obtained through a system_service_fetchers map data structure, then when is the data of this map object populated? By looking at the source code, we have a static code in Systemserviceregister that is primarily used to register the local Service interface, where the codes for the Windowmanagerservice Local Service are as follows:

registerService(Context.WINDOW_SERVICE, WindowManager.class,                new CachedServiceFetcher<WindowManager>() {            @Override            publiccreateService(ContextImpl ctx) {                returnnew WindowManagerImpl(ctx.getDisplay());            }});

All right It turns out that the windowmanager we get through Mcontext.getsystemservice is actually a Windowmanagerimpl object, and the AddView we call is the Windowmanagerimpl method of AddView.

This goes back to the first few things we explained, by calling Windowmanagerimpl to implement the layout file drawing process ....

Well, after a series of operations above, we have finished analyzing the loading and drawing process of Popupwindow, which is similar to the dialog,activity loading drawing process, which controls the loading and drawing process of the layout file through the Window object.

Summarize:

    • The Popupwindow interface loading and drawing process is also implemented through the Window object;

    • The Mwindowmanager object stored inside the Popupwindow is obtained through Contextimpl, and the Windowmanagerimpl object is obtained;

    • Popupwindow by adding a layer of package layout for the incoming view and overriding the Click event of the layout, realizing that the area outside the click Popupwindow Popupwindow disappear;

Android Source code parsing (21)-->popupwindow loading drawing process

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.