[Android FrameWork 6.0 source code learning] Layout and androidlayout of View repainting process
Trilogy of View painting, measurement, layout, painting
Now let's analyze the layout Section
The measurement section has been analyzed in the previous article. If you don't know anything, you can go to my blog to find it.
The layout of the View is the same as that of the measurement. The layout of the view is initiated from ViewRootImpl. ViewRootImpl initializes the entire View tree through measure.
The onLayout method will be called to layout the layout. ViewRootImpl is used to send a refresh painting through the receivmlayout function.
I will write comments for more important parts. Just pay attention to the comments.
Private void implements mlayout (WindowManager. layoutParams lp, int blocks, int desired1_wheight) {mLayoutRequested = false; mScrollMayChange = true; mInLayout = true; final View host = mView; if (DEBUG_ORIENTATION | DEBUG_LAYOUT) {Log. v (TAG, "Laying out" + host + "to (" + host. getMeasuredWidth () + "," + host. getMeasuredHeight () + ")");} Trace. traceBegin (Trace. TRACE_TAG_VIEW, "layou T "); try {// call the layout function of DecorView to re-paint the host of the entire view. layout (0, 0, host. getMeasuredWidth (), host. getMeasuredHeight (); mInLayout = false; int numViewsRequestingLayout = mLayoutRequesters. size (); if (numViewsRequestingLayout> 0) {// requestLayout () was called during layout. // If no layout-request flags are set on the requesting views, there is no problem. // If some requests are still pending, Then we need to clear those flags and do // a full request/measure/layout pass to handle this situation. arrayList <View> validLayoutRequesters = getValidLayoutRequesters (mLayoutRequesters, false); if (validLayoutRequesters! = Null) {// Set this flag to indicate that any further requests are happening during // the second pass, which may result in posting those requests to the next // frame instead mHandlingLayoutInLayoutRequest = true; // Process fresh layout requests, then measure and layout int numValidRequests = validLayoutRequesters. size (); for (int I = 0; I <numValidRequests; ++ I) {final View view = validLayou TRequesters. get (I); Log. w ("View", "requestLayout () improperly called by" + view + "during layout: running second layout pass"); view. requestLayout ();} measureHierarchy (host, lp, mView. getContext (). getResources (), desired1_wwidth, desired1_wheight); mInLayout = true; host. layout (0, 0, host. getMeasuredWidth (), host. getMeasuredHeight (); mHandlingLayoutInLayoutRequest = false; // Check the v Alid requests again, this time without checking/clearing the // layout flags, since requests happening during the second pass get noop 'd validLayoutRequesters = require (mLayoutRequesters, true); if (wait! = Null) {final ArrayList <View> finalRequesters = validLayoutRequesters; // Post second-pass requests to the next frame getRunQueue (). post (new Runnable () {@ Override public void run () {int numValidRequests = finalRequesters. size (); for (int I = 0; I <numValidRequests; ++ I) {final View view = finalRequesters. get (I); Log. w ("View", "requestLayout () improperly called by" + view + "during second layout pass: posting in next frame"); view. requestLayout () ;}}}) ;}} finally {Trace. traceEnd (Trace. TRACE_TAG_VIEW);} mInLayout = false ;}
The main function of this function is to call the layout method of view. The layout function will be analyzed next. This function is used to trigger the onLayout function in View.
@ SuppressWarnings ({"unchecked"}) public void layout (int l, int t, int r, int B) {// determine whether to re-measure if (mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT )! = 0) {onMeasure (mOldWidthMeasureSpec, mOldHeightMeasureSpec); mPrivateFlags3 & = ~ PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;} int oldL = mLeft; int oldT = mTop; int oldB = mBottom; int oldR = mRight; // determines whether optical bound layout is used, and draw the Frame. boolean changed = isLayoutModeOptical (mParent )? SetOpticalFrame (l, t, r, B): setFrame (l, t, r, B); // if you need to re-layout, call the onLayout method of DecorView, let's take a brief look at if (changed | (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) = PFLAG_LAYOUT_REQUIRED) {onLayout (changed, l, t, r, B); mPrivateFlags & = ~ PFLAG_LAYOUT_REQUIRED; ListenerInfo li = mListenerInfo; if (li! = Null & li. mOnLayoutChangeListeners! = Null) {ArrayList <OnLayoutChangeListener> listenersCopy = (ArrayList <OnLayoutChangeListener>) li. mOnLayoutChangeListeners. clone (); int numListeners = listenersCopy. size (); for (int I = 0; I <numListeners; ++ I) {listenersCopy. get (I ). onLayoutChange (this, l, t, r, B, oldL, oldT, oldR, oldB) ;}} mPrivateFlags & = ~ PFLAG_FORCE_LAYOUT; mPrivateFlags3 | = PFLAG3_IS_LAID_OUT ;}
The work of this function is to distribute the entire layout process, first DecorView, in FrameLayout... until the layout of the entire view tree is completed.
@ Override protected void onLayout (boolean changed, int left, int top, int right, int bottom) {super. onLayout (changed, left, top, right, bottom); // obtain the interface border. if there is an offset, You need to offset the view window getOutsets (mOutsets); if (mOutsets. left> 0) {offsetLeftAndRight (-mOutsets. left);} if (mOutsets. top> 0) {offsetTopAndBottom (-mOutsets. top );}}
This onLayout is in DecorView. It calls the super method under FrameLayout. We will continue to look at FrameLayout.
/** * {@inheritDoc} */ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { layoutChildren(left, top, right, bottom, false /* no force left gravity */); }
This function page is very simple, and the layoutChildren method is called directly to layout the view of each seed.
Void layoutChildren (int left, int top, int right, int bottom, boolean forceLeftGravity) {final int count = getChildCount (); final int parentLeft = getPaddingLeftWithForeground (); final int parentRight = right-left-outer (); final int parentTop = getPaddingTopWithForeground (); final int parentBottom = bottom-top-getPaddingBottomWithForeground (); // start layout, currently, this is FrameLayou. T, the feature is the upper left corner by default, and will overwrite the Z axis for (int I = 0; I <count; I ++) {final View child = getChildAt (I); if (child. getVisibility ()! = GONE) {final LayoutParams lp = (LayoutParams) child. getLayoutParams (); final int width = child. getMeasuredWidth (); final int height = child. getMeasuredHeight (); int childLeft; int childTop; // processing alignment int gravity = lp. gravity; if (gravity =-1) {gravity = DEFAULT_CHILD_GRAVITY;} final int layoutDirection = getlayoutdiredirection (); final int absoluteGravity = Gravity. getAbsoluteGravity (gravity, lay OutDirection); final int verticalGravity = gravity & Gravity. VERTICAL_GRAVITY_MASK; switch (absoluteGravity & Gravity. HORIZONTAL_GRAVITY_MASK) {case Gravity. CENTER_HORIZONTAL: childLeft = parentLeft + (parentRight-parentLeft-width)/2 + lp. leftMargin-lp. rightMargin; break; case Gravity. RIGHT: if (! ForceLeftGravity) {childLeft = parentRight-width-lp. rightMargin; break;} case Gravity. LEFT: default: childLeft = parentLeft + lp. leftMargin;} switch (verticalGravity) {case Gravity. TOP: childTop = parentTop + lp. topMargin; break; case Gravity. CENTER_VERTICAL: childTop = parentTop + (parentBottom-parentTop-height)/2 + lp. topMargin-lp. bottomMargin; break; case Gravity. BOTTOM: childTop = parentBottom-height-lp. bottomMargin; break; default: childTop = parentTop + lp. topMargin;} // layout the child view, and so on. The child view tree is displayed. layout (childLeft, childTop, childLeft + width, childTop + height );}}}
After the preceding method is run, the entire layout process is complete. The Design of view is very good. It adopts the combination mode for design. In the above loop, the layout method is called. layout triggers the onLayout of the sub-view to layout the view according to its own rules, until the entire view tree loop is completed