Source code to interpret the layout of view in Android

Source: Internet
Author: User
Tags event listener

Android Veiw from memory to rendering on the UI interface needs to go through three stages: acreage, layout, and the overall mechanism for view acreage, layout, and drawing can be found in the blog "View layout and drawing mechanism in Android". Volume is the basis of the layout, if you want to know the details of acreage, you can see the blog "Source resolution Android View measure acreage process." This article will analyze the layout of view from the source point of view, this article will detail the view layout process of the key methods, and the source code annotated to explain.

The purpose of the layout of the view is to calculate the size of the view and the position in its parent control, specifically to calculate the distance from the four boundaries of the view to the left, top, and top boundaries of its parent control, which is the value of calculating the view's leftmost, upper, right, bottom.

Layout

The layout () method is the entrance to the view layout, and its source code is as follows:

     Public void Layout(intLintTintRintb) {///member variable MPRIVATEFLAGS3 some bits store information related to layout        if((MPRIVATEFLAGS3 & pflag3_measure_needed_before_layout)! =0) {//If the value of the 4th bit (from the right-most to the 4th bit) of the low byte in MPRIVATEFLAGS3 is 1,            //Then it means that you need to acreage the view before layout.            //In this case, the Onmeasure method of view is executed to acreage the viewOnmeasure (Moldwidthmeasurespec, Moldheightmeasurespec);///Acreage resets the 4th bit of the MPRIVATEFLAGS3 low byte to 0 after completion,            //Remove label Pflag3_measure_needed_before_layoutMPRIVATEFLAGS3 &= ~pflag3_measure_needed_before_layout; }intOLDL = Mleft;intOldt = Mtop;intOldb = Mbottom;intOldr = Mright;//If Islayoutmodeoptical () returns True, then the Setopticalframe () method is executed,        //Otherwise the Setframe () method will be executed. and Setopticalframe () internally calls Setframe (),        //So the Setframe () method will be executed anyway.         The //setframe () method stores the view's new left, top, right, and bottom in the view's member variable        //And returns a Boolean value that returns true to indicate that the location or size of the view has changed.        //Otherwise indicates that no change has occurredBoolean changed = Islayoutmodeoptical (mparent)? Setopticalframe (L, T, R, B): Setframe (L, T, R, b);if(Changed | | (Mprivateflags & pflag_layout_required) = = pflag_layout_required) {//If the layout of the view has changed, or if the Mprivateflags has a label pflag_layout_required that requires layout,            //Then the following code will be executed            //The execution of the OnLayout method is triggered first, and the default OnLayout method in view is an empty method            //But classes inheriting from ViewGroup need to implement the OnLayout method in order to loop the child view sequentially in the OnLayout method ,            //And call the layout method of the sub viewOnLayout (changed, L, T, R, b);after executing the OnLayout method, remove the label from the Mprivateflags pflag_layout_requiredMprivateflags &= ~pflag_layout_required;//We can use the View addonlayoutchangelistener (View.onlayoutchangelistener listener) method            //Add multiple event listeners to the view that have changed layout            //These event listeners are stored in mlistenerinfo.monlayoutchangelisteners this ArrayListListenerinfo li = mlistenerinfo;if(Li! =NULL&& Li.monlayoutchangelisteners! =NULL) {//First copy the event listener in MonlayoutchangelistenersArraylist<onlayoutchangelistener> listenerscopy = (arraylist<onlayoutchangelistener>) li . Monlayoutchangelisteners.clone ();intNumlisteners = Listenerscopy.size (); for(inti =0; i < numlisteners; ++i) {//Traverse the registered event listener and call its Onlayoutchange method in turn, so that the Layout event listener respondsListenerscopy.Get(i). Onlayoutchange ( This, L, T, R, B, Oldl, Oldt, Oldr, OLDB); }            }        }//Remove mandatory LAYOUT label from Mprivateflags pflag_force_layoutMprivateflags &= ~pflag_force_layout;//Adding layout-completed labels to MPRIVATEFLAGS3 pflag3_is_laid_outMPRIVATEFLAGS3 |= pflag3_is_laid_out; }
  • At the beginning of the layout () method, the first step is to determine whether the onmeasure () of the view needs to be executed based on whether the MPRIVATEFLAGS3 variable has a flag bit pflag3_measure_needed_before_layout Method. If you have a flag bit pflag3_measure_needed_before_layout, the Onmeasure () method is executed to acreage the view, and the acreage result is saved to the member variable of the view. When the acreage is complete, the 4th bit of the MPRIVATEFLAGS3 low byte is reset to 0, removing the label pflag3_measure_needed_before_layout.

  • If Islayoutmodeoptical () returns True, then the Setopticalframe () method is executed, otherwise the Setframe () method is executed. and Setopticalframe () internally calls Setframe (), so the Setframe () method will be executed anyway. The Setframe () method stores the new left, top, right, and bottom of the view in the member variable of the view, and returns a Boolean value that indicates that the position or size of the view has changed, otherwise it has not changed. The Setframe () method is described in more detail later.

  • If the layout of the view changes, or if Mprivateflags has a label pflag_layout_required that requires layout, the execution of the OnLayout method is triggered, and the default OnLayout method in view is an empty method. However, classes that inherit from ViewGroup need to implement the OnLayout method, looping the child view in turn in the OnLayout method, and invoking the layout method of the child view. After the OnLayout method is executed, remove the label pflag_layout_required from the Mprivateflags. It then iterates through the registered layout Change event listener, calling its Onlayoutchange method in turn, so that the layout event listener responds.

  • Finally, remove the label pflag_force_layout of the forced layout from the Mprivateflags, and add the label pflag3_is_laid_out to the MPRIVATEFLAGS3 to complete the layout.

Setframe

The Setframe () method is specifically used to assign dimensions and positions to the view, and the Setframe () method is called in the layout () method. Its source code is as follows:

    protected Boolean Setframe(intLeftintTopintRightintBottom) {BooleanChanged =false;if(DBG) {LOG.D ("View", This+"View.setframe ("+ Left +","+ Top +","+ Right +","+ Bottom +")"); }if(Mleft! = left | | Mright! = RIGHT | | Mtop! = TOP | | Mbottom! = bottom) {//Compare the old left, right, top, and bottom, as long as the layout of the view changes if not completely relative            //Set the changed variable to TrueChanged =true;//Save the Pflag_drawn tag information in mprivateflags first            intDrawn = Mprivateflags & pflag_drawn;//Calculate the new and old dimensions of view separately            intOldWidth = Mright-mleft;intOldHeight = Mbottom-mtop;intNewwidth = Right-left;intNewheight = Bottom-top;//Compare the old and new dimensions of view, if the dimensions have changed, then the value of sizechanged is true            BooleansizeChanged = (newwidth! = oldwidth) | | (Newheight! = oldheight);//Invalidate our old positionInvalidate (sizeChanged);//Store New Left, top, right, bottom in member variables of viewMleft = left;            Mtop = top;            Mright = right; Mbottom = bottom;the//mrendernode.setlefttoprightbottom () method invokes the Nsetlefttoprightbottom () method of the Rendernode native method,            //This method updates the display list for rendering based on left, top, right, bottomMrendernode.setlefttoprightbottom (Mleft, Mtop, Mright, Mbottom);//Add label pflag_has_bounds to Mprivateflags to indicate that the current view has a clear boundary rangeMprivateflags |= pflag_has_bounds;if(sizeChanged) {//If the view size has changed compared to the previous, then the Sizechange () method is executed,                the Onsizechanged () method is called in the method, and the new and old dimensions of the view are passed inSizechange (Newwidth, Newheight, OldWidth, oldheight); }if((Mviewflags & visibility_mask) = = VISIBLE | | Mghostview! =NULL) {//It is possible that the Invalidate method is called before calling the Setframe method.                //This will cause Mprivateflags to remove the pflag_drawn tag.                 //If the current view is visible, Mprivateflags forces the Pflag_drawn state bit to be added.                //This will ensure that the following invalidate () method executes to its parent control level. Mprivateflags |= Pflag_drawn; Invalidate (sizeChanged);The //invalidateparentcaches () method removes the Pflag_invalidated label from its parent control.                //So the parent control rebuilds the display list for renderingInvalidateparentcaches (); }//re-restore Mprivateflags pflag_drawn tag informationMprivateflags |= drawn; Mbackgroundsizechanged =true;if(Mforegroundinfo! =NULL) {mforegroundinfo.mboundschanged =true;        } notifysubtreeaccessibilitystatechangedifneeded (); }returnChanged }
    • In this method, the old left, right, top, and bottom are compared, and the changed variable is set to true as long as the layout of the view changes if not identical. Then compare whether the new and old dimensions of the view are the same, if the dimensions have changed and saved to the variable sizechanged. If the dimensions have changed, the value of sizechanged is true.

    • Then save the new left, top, right, and bottom stored in the view's member variable. and executes the Mrendernode.setlefttoprightbottom () method, which invokes the Nsetlefttoprightbottom () method of the Rendernode native method, which is based on the left, top, right, Bottom updates the display list for rendering.

    • If the size of the view changes compared to the previous, then the Sizechange () method is executed, and the method calls the Onsizechanged () method, passing in the new and old dimensions of the view.

    • If the view is visible, then the invalidate and Invalidateparentcaches methods are called. The Invalidateparentcaches () method removes the Pflag_invalidated label from its parent control, so that its parent control rebuilds the display list for rendering.

Sizechange

The Sizechange method is called when the dimension of the view changes, and the Sizechange () method may be called in the Setframe () method. Of course, the Sizechange () method is also called in the View's Setleft (), Settop (), Setright (), Setbottom (), and other methods that change the view size, with the source code as follows:

    privatevoidsizeChange(intintintint oldHeight) {        //将View的新旧尺寸传递给onSizeChanged()方法        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);        ifnull) {            mOverlay.getOverlayView().setRight(newWidth);            mOverlay.getOverlayView().setBottom(newHeight);        }        rebuildOutline();    }

In this method, it mainly passes the new and old dimensions of view to the Onsizechanged () method to make it execute.

Onsizechanged

The Onsizechanged () method is an empty method, and the code looks like this:

    protectedvoidonSizeChanged(intintintint oldh) {    }

This method is called when the dimension of the view changes, through the execution of the Sizechange () method. This method is also called when the view is first added to the view tree, except that the incoming old size oldwidth and OldHeight are all 0.

Summarize

The overall calling procedure of the layout method is as follows:

Onmeasure (), Setframe (), Sizechange (), OnLayout (), onsizechanged (), layout (), Traverse execution Onlayoutch Angelistener.onlayoutchange ()

I hope this article will help you understand the layout process of the view!

Related reading:
"My Android Blog compilation"
The layout and drawing mechanism of view in Android
"Source code to resolve the measure acreage process in Android View"

Source code to interpret the layout of view in Android

Related Article

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.