View layout process in Android

Source: Internet
Author: User

View layout process in Android

In Android, Veiw goes through three phases in sequence from memory to display on the UI: Traffic calculation-> Layout-> drawing, for details about the overall mechanism of View calculation, layout, and drawing, see the layout and Drawing Mechanism of View in Android. Traffic is the basis of the layout. If you want to know details about the traffic calculation, see the "measurement process of View in the source code parsing Android" blog. This article will parse the layout process of the View layout from the source code perspective. This article will introduce the key methods in the View layout process in detail, and add comments to the source code for instructions.

The purpose of the View layout is to calculate the size of the View and its position in its parent control. Specifically, it is to calculate the distance between the four boundaries of the View to the Left Border of its parent control and the upper border respectively, calculate the left, top, right, and bottom values of the View.

Layout

The layout () method is the entry to the View layout. The source code is as follows:

Public void layout (int l, int t, int r, int B) {// some bits in the member variable mPrivateFlags3 store layout-related information if (mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT )! = 0) {// if the value of mPrivateFlags3's low byte's 4th bits (4th bits from the rightmost to the left) is 1, // you need to calculate the volume of the View before layout. // In this case, the onMeasure method of the View is executed to calculate the volume of the View onMeasure (mOldWidthMeasureSpec, mOldHeightMeasureSpec ); // After the calculation is complete, the 4th-bit mPrivateFlags3 low byte is reset to 0. // remove the label PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT mPrivateFlags3 & = ~ Struct;} int oldL = mLeft; int oldT = mTop; int oldB = mBottom; int oldR = mRight; // If isLayoutModeOptical () returns true, setOpticalFrame () is executed () method, // otherwise the setFrame () method will be executed. In addition, setOpticalFrame () calls setFrame (), // The setFrame () method will be executed in any case. // The setFrame () method stores the new left, top, right, and bottom values in the View member variables. // a boolean value is returned, if true is returned, it indicates that the position or size of the View has changed. // otherwise, it indicates that no change has occurred. boolean changed = isLayoutModeOptical (mParent )? SetOpticalFrame (l, t, r, B): setFrame (l, t, r, B); if (changed | (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) = PFLAG_LAYOUT_REQUIRED) {// if the View LAYOUT changes, or the mPrivateFlags has the label PFLAG_LAYOUT_REQUIRED for LAYOUT, // the following code is executed. // The onLayout method is triggered first, the default onLayout method in the View is an empty method // However, the onLayout method must be implemented for Classes inherited from the ViewGroup, so that the onLayout method can loop through the Child View in sequence, // call the layout method onLayout (changed, l, t, r, B) OF THE subview. // After the onLayout method is executed Remove the label PFLAG_LAYOUT_REQUIRED mPrivateFlags from ags & = ~ PFLAG_LAYOUT_REQUIRED; // you can use the addOnLayoutChangeListener (View. onLayoutChangeListener listener) method // Add multiple event listeners with changed Layout to the View. // These event listeners are stored in mListenerInfo. mOnLayoutChangeListeners ListenerInfo li = mListenerInfo; if (li! = Null & li. mOnLayoutChangeListeners! = Null) {// first copy the event listener in mOnLayoutChangeListeners to the ArrayList
  
   
ListenersCopy = (ArrayList
   
    
) Li. mOnLayoutChangeListeners. clone (); int numListeners = listenersCopy. size (); for (int I = 0; I <numListeners; ++ I) {// traverses the registered event listener and calls its onLayoutChange method in sequence, in this way, the Layout event listener will receive a response to listenersCopy. get (I ). onLayoutChange (this, l, t, r, B, oldL, oldT, oldR, oldB) ;}}// remove the label PFLAG_FORCE_LAYOUT mPrivateFlags that forces Layout from mPrivateFlags & = ~ PFLAG_FORCE_LAYOUT; // Add the label PFLAG3_IS_LAID_OUT mPrivateFlags3 completed by Layout to mPrivateFlags3 | = PFLAG3_IS_LAID_OUT ;}
   
  

At the beginning of execution of the layout () method, the onMeasure () method of View is determined based on whether the mPrivateFlags3 variable has a flag PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT. If PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT has a flag, the onMeasure () method is executed to calculate the volume of the View. The result of the calculation is saved to the member variable of the View. After the calculation is complete, the 4th-bit mPrivateFlags3 low byte is reset to 0 and the label PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT is removed.

If isLayoutModeOptical () returns true, the setOpticalFrame () method is executed; otherwise, the setFrame () method is executed. SetOpticalFrame () calls setFrame () internally, so the setFrame () method is executed in any case. The setFrame () method stores the new left, top, right, and bottom values in the View member variables and returns a boolean value, if true is returned, the position or size of the View has changed. Otherwise, the View has not changed. The setFrame () method will be described in detail later.

If the View LAYOUT changes, or mPrivateFlags has the label PFLAG_LAYOUT_REQUIRED that requires LAYOUT, the onLayout method is triggered. The default onLayout method in the View is an empty method. However, classes inherited from ViewGroup all need to implement the onLayout method, so that the onLayout method loops through the subview in sequence and calls the layout method of the subview. After the onLayout method is executed, remove the label PFLAG_LAYOUT_REQUIRED from mPrivateFlags. Then, the system traverses the registered Layout Change event listener and calls its onLayoutChange method in turn, so that the Layout event listener gets a response.

Finally, remove the force Layout label PFLAG_FORCE_LAYOUT from mPrivateFlags and add the completed label PFLAG3_IS_LAID_OUT to mPrivateFlags3.

SetFrame

The setFrame () method is used to assign dimensions and positions to the View. The setFrame () method is called in the layout () method. The source code is as follows:

Protected boolean setFrame (int left, int top, int right, int bottom) {boolean changed = 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 and new left, right, top, and bottom. If they are not completely relative, the View layout has changed, // set the changed variable to true changed = true; // first save the PFLAG_DRAWN Tag Information in mPrivateFlags int drawn = mPrivateFlags & PFLAG_DRAWN; // calculate the New and Old dimensions of the View respectively. int oldWidth = mRight-mLeft; int oldHeight = mBottom-mTop; int newWidth = right-left; int newHeight = bottom-top; // compare whether the new and old dimensions of the View are the same. If the size changes, the value of sizeChanged is true boolean sizeChanged = (newWidth! = OldWidth) | (newHeight! = OldHeight); // Invalidate our old position invalidate (sizeChanged); // store the new left, top, right, and bottom in the View member variable mLeft = left; mTop = top; mRight = right; mBottom = bottom; // mRenderNode. the setLeftTopRightBottom () method calls the nSetLeftTopRightBottom () method of the original method in the RenderNode. // This method updates the display list mRenderNode used for rendering based on left, top, right, and bottom. setLeftTopRightBottom (mLeft, mTop, mRight, mBottom); // Add the label PFLAG_HAS_BOUNDS to mPrivateFlags, table Shows that the current View has a clear boundary range mPrivateFlags | = PFLAG_HAS_BOUNDS; if (sizeChanged) {// if the size of the View changes compared with the previous one, the sizeChange () method is executed, // The onSizeChanged () method is called in this method, and the new and old dimensions of the View are passed to sizeChange (newWidth, newHeight, oldWidth, oldHeight);} if (mViewFlags & VISIBILITY_MASK) = VISIBLE | mGhostView! = Null) {// The invalidate method may be called before the setFrame method is called. // This causes mPrivateFlags to remove the PFLAG_DRAWN label. // If the current View is visible, add the PFLAG_DRAWN status bit to mPrivateFlags. // This ensures that the following invalidate () method is executed at the parent control level. MPrivateFlags | = PFLAG_DRAWN; invalidate (sizeChanged); // The invalidateParentCaches () method removes the PFLAG_INVALIDATED tag of its parent control, // The parent control will recreate the display list for rendering. invalidateParentCaches ();} // restore the original PFLAG_DRAWN Tag Information mPrivateFlags in mPrivateFlags | = drawn; mBackgroundSizeChanged = true; if (mForegroundInfo! = Null) {mForegroundInfo. mBoundsChanged = true;} policysubtreeaccessibilitystatechangedifneeded ();} return changed ;}

In this method, the new and old left, right, top, and bottom are compared. If they are not identical, the layout of the View is changed, and the changed variable is set to true. Then compare whether the new and old dimensions of the View are the same. If the size changes, save it to the sizeChanged variable. If the size changes, the value of sizeChanged is true.

Save the new left, top, right, and bottom values to the member variables of the View. Run mRenderNode. the setLeftTopRightBottom () method calls the nSetLeftTopRightBottom () method of the original method in the RenderNode. This method updates the display list for rendering based on left, top, right, and bottom.

If the size of the View changes compared to the previous one, the sizeChange () method is executed. The onSizeChanged () method is called in this method, and the new and old size of the View is passed in.

If the View is visible, the invalidate and invalidateParentCaches methods are called. The invalidateParentCaches () method removes the PFLAG_INVALIDATED tag of its parent control, so that its parent control reconstructs the display list for rendering.

SizeChange

The sizeChange method is called when the View Size changes. The sizeChange () method may be called in the setFrame () method. Of course, the sizeChange () method is also called in the setLeft (), setTop (), setRight (), setBottom (), and other methods for changing the View size. The source code is as follows:

Private void sizeChange (int newWidth, int newHeight, int oldWidth, int oldHeight) {// pass the New and Old size of the View to the onSizeChanged () method onSizeChanged (newWidth, newHeight, oldWidth, oldHeight); if (mOverlay! = Null) {mOverlay. getOverlayView (). setRight (newWidth); mOverlay. getOverlayView (). setBottom (newHeight);} rebuildOutline ();}

In this method, the new and old dimensions of the View are passed to the onSizeChanged () method for execution.

OnSizeChanged

The onSizeChanged () method is an empty method. The Code is as follows:

    protected void onSizeChanged(int w, int h, int oldw, int oldh) {    }

This method is called by executing the sizeChange () method when the size of the View changes. When a View is added to the View tree for the first time, this method will also be called, except that the old size oldWidth and oldHeight passed in are both 0.

Summary

The main line for calling the layout method is as follows:

Layout ()-> onMeasure ()-> setFrame ()-> sizeChange ()-> onSizeChanged ()-> onLayout ()-> traverse and execute OnLayoutChangeListener. onLayoutChange ()

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

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.