View layout of Android GUI, androidguiview

Source: Internet
Author: User

View layout of Android GUI, androidguiview

After understanding the first measurement in the View rendering mechanism, we will continue to understand the second process of analyzing the View rendering, that is, layout positioning. Continue to trace and analyze the source code. Based on the previous process analysis, we know that the View is drawn from the RootViewImpl's javasmtraversals method, in this method, performMeasure, performLayout, and performDraw are called in sequence for measurement, layout, and drawing. Let's take a look at what has been done in performLayout, the key source code of this method is as follows:

private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,            int desiredWindowHeight) {        mLayoutRequested = false;        mScrollMayChange = true;        mInLayout = true;        final View host = mView;          ……        try {            host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());……        } finally {            Trace.traceEnd(Trace.TRACE_TAG_VIEW);        }        mInLayout = false;    }

From this, we can see that the most critical code is to call the host. layout method, so we can't remember what host is? By the way, it is the Root View DecorView we mentioned earlier. Then we will go back to DecorView to see what it has done in the layout method. We did not find this method in DecorView. Don't worry. Based on the inheritance system of this class, we finally tracked the layout method in View.

public void layout(int l, int t, int r, int b) {        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;        boolean changed = isLayoutModeOptical(mParent) ?                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);        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;    }protected void onLayout(boolean changed, int left, int top, int right, int bottom) {}

The four parameters in this method represent the distance between the current View and the parent View. It can be seen from the description that this method should not be overwritten by the quilt class, if you need to re-layout, You can override onLayout In the subclass. This method is an empty method in the View, and nothing is written. In fact, the layout method is not identified as final in the View, which means it can be overwritten.

Continue to view the relevant code in ViewGoup. As a result, layout is overwritten and the final ID is added. At the same time, onLayout is identified as an abstract method, so the class inherited from ViewGroup is, the layout method cannot be rewritten, And the onLayout method must be implemented. From the code, we can see that although ViewGroup overwrites layout, it actually calls the layout of View, and then calls the onLayout method to locate the layout.

       @Override    public final void layout(int l, int t, int r, int b) {        if (!mSuppressLayout && (mTransition == null || !mTransition.isChangingLayout())) {            if (mTransition != null) {                mTransition.layoutChange(this);            }            super.layout(l, t, r, b);        } else {            // record the fact that we noop'd it; request layout when transition finishes            mLayoutCalledWhileSuppressed = true;        }    }    @Override    protected abstract void onLayout(boolean changed,            int l, int t, int r, int b);

In DecorView, The onLayout method is not found, so it must be in its parent class FrameLayout. Find the source code of FrameLayout and you can see the onLayout method, as shown below:

  @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        layoutChildren(left, top, right, bottom, false /* no force left gravity */);    }    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 - getPaddingRightWithForeground();        final int parentTop = getPaddingTopWithForeground();        final int parentBottom = bottom - top - getPaddingBottomWithForeground();        mForegroundBoundsChanged = true;                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;                int gravity = lp.gravity;                if (gravity == -1) {                    gravity = DEFAULT_CHILD_GRAVITY;                }                final int layoutDirection = getLayoutDirection();                final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);                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;                }                child.layout(childLeft, childTop, childLeft + width, childTop + height);            }        }    }

From the method, we can see that the layoutChildren method is finally called in Framelayout, in this method, the layout method is called for layout for each View in the container Based on the measurement results and some layout attributes. Based on the above code analysis, we can find the following flowchart of View layout positioning.

 

For questions or technical exchanges, please join the official QQ group: (452379712)

 

Author: Jerry Education
Source: http://www.cnblogs.com/jerehedu/
The copyright of this article belongs to Yantai Jerry Education Technology Co., Ltd. and the blog Park. You are welcome to repost it. However, you must keep this statement without the author's consent and provide the original article connection on the article page, otherwise, you are entitled to pursue legal liability.

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.