Android LinearLayout(7.1) 源码解析

来源:互联网 发布:银行卡网络异地消费 编辑:程序博客网 时间:2024/06/16 09:42

这一节,将分析LinearLayout的onMeasure和onLayout两个方法
1、onMeasure由measureVertical 和measureHorizontal两个方法组成
2、onLayout由layoutVertical 和layoutHorizontal两个方法组成
下面,只分别分析measureVertical 和onLayoutVertical这两个方法

先来看一下onMeasureVertical

void measureVertical(int widthMeasureSpec, int heightMeasureSpec) {        mTotalLength = 0;        int maxWidth = 0;        int childState = 0;        int alternativeMaxWidth = 0;        int weightedMaxWidth = 0;        boolean allFillParent = true;        float totalWeight = 0;        final int count = getVirtualChildCount();        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);        boolean matchWidth = false;        boolean skippedMeasure = false;        final int baselineChildIndex = mBaselineAlignedChildIndex;                final boolean useLargestChild = mUseLargestChild;        int largestChildHeight = Integer.MIN_VALUE;        int consumedExcessSpace = 0;        // See how tall everyone is. Also remember max width.        for (int i = 0; i < count; ++i) {            final View child = getVirtualChildAt(i);            if (child == null) {                mTotalLength += measureNullChild(i);                continue;            }            if (child.getVisibility() == View.GONE) {               i += getChildrenSkipCount(child, i);               continue;            }            if (hasDividerBeforeChildAt(i)) {                mTotalLength += mDividerHeight;            }            final LayoutParams lp = (LayoutParams) child.getLayoutParams();            totalWeight += lp.weight;            final boolean useExcessSpace = lp.height == 0 && lp.weight > 0;            if (heightMode == MeasureSpec.EXACTLY && useExcessSpace) {                // Optimization: don't bother measuring children who are only                // laid out using excess space. These views will get measured                // later if we have space to distribute.                final int totalLength = mTotalLength;                mTotalLength = Math.max(totalLength, totalLength + lp.topMargin + lp.bottomMargin);                skippedMeasure = true;            } else {                if (useExcessSpace) {                    // The heightMode is either UNSPECIFIED or AT_MOST, and                    // this child is only laid out using excess space. Measure                    // using WRAP_CONTENT so that we can find out the view's                    // optimal height. We'll restore the original height of 0                    // after measurement.                    lp.height = LayoutParams.WRAP_CONTENT;                }                // Determine how big this child would like to be. If this or                // previous children have given a weight, then we allow it to                // use all available space (and we will shrink things later                // if needed).                final int usedHeight = totalWeight == 0 ? mTotalLength : 0;                measureChildBeforeLayout(child, i, widthMeasureSpec, 0,                        heightMeasureSpec, usedHeight);                final int childHeight = child.getMeasuredHeight();                if (useExcessSpace) {                    // Restore the original height and record how much space                    // we've allocated to excess-only children so that we can                    // match the behavior of EXACTLY measurement.                    lp.height = 0;                    consumedExcessSpace += childHeight;                }                final int totalLength = mTotalLength;                mTotalLength = Math.max(totalLength, totalLength + childHeight + lp.topMargin +                       lp.bottomMargin + getNextLocationOffset(child));                if (useLargestChild) {                    largestChildHeight = Math.max(childHeight, largestChildHeight);                }            }            /**             * If applicable, compute the additional offset to the child's baseline             * we'll need later when asked {@link #getBaseline}.             */            if ((baselineChildIndex >= 0) && (baselineChildIndex == i + 1)) {               mBaselineChildTop = mTotalLength;            }            // if we are trying to use a child index for our baseline, the above            // book keeping only works if there are no children above it with            // weight.  fail fast to aid the developer.            if (i < baselineChildIndex && lp.weight > 0) {                throw new RuntimeException("A child of LinearLayout with index "                        + "less than mBaselineAlignedChildIndex has weight > 0, which "                        + "won't work.  Either remove the weight, or don't set "                        + "mBaselineAlignedChildIndex.");            }            boolean matchWidthLocally = false;            if (widthMode != MeasureSpec.EXACTLY && lp.width == LayoutParams.MATCH_PARENT) {                // The width of the linear layout will scale, and at least one                // child said it wanted to match our width. Set a flag                // indicating that we need to remeasure at least that view when                // we know our width.                matchWidth = true;                matchWidthLocally = true;            }            final int margin = lp.leftMargin + lp.rightMargin;            final int measuredWidth = child.getMeasuredWidth() + margin;            maxWidth = Math.max(maxWidth, measuredWidth);            childState = combineMeasuredStates(childState, child.getMeasuredState());            allFillParent = allFillParent && lp.width == LayoutParams.MATCH_PARENT;            if (lp.weight > 0) {                /*                 * Widths of weighted Views are bogus if we end up                 * remeasuring, so keep them separate.                 */                weightedMaxWidth = Math.max(weightedMaxWidth,                        matchWidthLocally ? margin : measuredWidth);            } else {                alternativeMaxWidth = Math.max(alternativeMaxWidth,                        matchWidthLocally ? margin : measuredWidth);            }            i += getChildrenSkipCount(child, i);        }        if (mTotalLength > 0 && hasDividerBeforeChildAt(count)) {            mTotalLength += mDividerHeight;        }        if (useLargestChild &&                (heightMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.UNSPECIFIED)) {            mTotalLength = 0;            for (int i = 0; i < count; ++i) {                final View child = getVirtualChildAt(i);                if (child == null) {                    mTotalLength += measureNullChild(i);                    continue;                }                if (child.getVisibility() == GONE) {                    i += getChildrenSkipCount(child, i);                    continue;                }                final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)                        child.getLayoutParams();                // Account for negative margins                final int totalLength = mTotalLength;                mTotalLength = Math.max(totalLength, totalLength + largestChildHeight +                        lp.topMargin + lp.bottomMargin + getNextLocationOffset(child));            }        }        // Add in our padding        mTotalLength += mPaddingTop + mPaddingBottom;        int heightSize = mTotalLength;        // Check against our minimum height        heightSize = Math.max(heightSize, getSuggestedMinimumHeight());        // Reconcile our calculated size with the heightMeasureSpec        int heightSizeAndState = resolveSizeAndState(heightSize, heightMeasureSpec, 0);        heightSize = heightSizeAndState & MEASURED_SIZE_MASK;        // Either expand children with weight to take up available space or        // shrink them if they extend beyond our current bounds. If we skipped        // measurement on any children, we need to measure them now.        int remainingExcess = heightSize - mTotalLength                + (mAllowInconsistentMeasurement ? 0 : consumedExcessSpace);        if (skippedMeasure || remainingExcess != 0 && totalWeight > 0.0f) {            float remainingWeightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;            mTotalLength = 0;            for (int i = 0; i < count; ++i) {                final View child = getVirtualChildAt(i);                if (child == null || child.getVisibility() == View.GONE) {                    continue;                }                final LayoutParams lp = (LayoutParams) child.getLayoutParams();                final float childWeight = lp.weight;                if (childWeight > 0) {                    final int share = (int) (childWeight * remainingExcess / remainingWeightSum);                    remainingExcess -= share;                    remainingWeightSum -= childWeight;                    final int childHeight;                    if (mUseLargestChild && heightMode != MeasureSpec.EXACTLY) {                        childHeight = largestChildHeight;                    } else if (lp.height == 0 && (!mAllowInconsistentMeasurement                            || heightMode == MeasureSpec.EXACTLY)) {                        // This child needs to be laid out from scratch using                        // only its share of excess space.                        childHeight = share;                    } else {                        // This child had some intrinsic height to which we                        // need to add its share of excess space.                        childHeight = child.getMeasuredHeight() + share;                    }                    final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(                            Math.max(0, childHeight), MeasureSpec.EXACTLY);                    final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,                            mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin,                            lp.width);                    child.measure(childWidthMeasureSpec, childHeightMeasureSpec);                    // Child may now not fit in vertical dimension.                    childState = combineMeasuredStates(childState, child.getMeasuredState()                            & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));                }                final int margin =  lp.leftMargin + lp.rightMargin;                final int measuredWidth = child.getMeasuredWidth() + margin;                maxWidth = Math.max(maxWidth, measuredWidth);                boolean matchWidthLocally = widthMode != MeasureSpec.EXACTLY &&                        lp.width == LayoutParams.MATCH_PARENT;                alternativeMaxWidth = Math.max(alternativeMaxWidth,                        matchWidthLocally ? margin : measuredWidth);                allFillParent = allFillParent && lp.width == LayoutParams.MATCH_PARENT;                final int totalLength = mTotalLength;                mTotalLength = Math.max(totalLength, totalLength + child.getMeasuredHeight() +                        lp.topMargin + lp.bottomMargin + getNextLocationOffset(child));            }            // Add in our padding            mTotalLength += mPaddingTop + mPaddingBottom;            // TODO: Should we recompute the heightSpec based on the new total length?        } else {            alternativeMaxWidth = Math.max(alternativeMaxWidth,                                           weightedMaxWidth);            // We have no limit, so make all weighted views as tall as the largest child.            // Children will have already been measured once.            if (useLargestChild && heightMode != MeasureSpec.EXACTLY) {                for (int i = 0; i < count; i++) {                    final View child = getVirtualChildAt(i);                    if (child == null || child.getVisibility() == View.GONE) {                        continue;                    }                    final LinearLayout.LayoutParams lp =                            (LinearLayout.LayoutParams) child.getLayoutParams();                    float childExtra = lp.weight;                    if (childExtra > 0) {                        child.measure(                                MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(),                                        MeasureSpec.EXACTLY),                                MeasureSpec.makeMeasureSpec(largestChildHeight,                                        MeasureSpec.EXACTLY));                    }                }            }        }        if (!allFillParent && widthMode != MeasureSpec.EXACTLY) {            maxWidth = alternativeMaxWidth;        }        maxWidth += mPaddingLeft + mPaddingRight;        // Check against our minimum width        maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());        setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),                heightSizeAndState);        if (matchWidth) {            forceUniformWidth(count, heightMeasureSpec);        }    }

上面code的主要功能如下:
1、判断每一个subchild之前是否有divider
2、计算每一个subchild的宽和高
3、如果subchild设置了weight,根据weight来计算subchild的高
4、是否使用useLargestChild,是的话则找出subchild中height最大的一个value,然后设置每一个subchild的height都为这个value
5、测量linearLayout本身的宽和高

下面我们一点一点的分析measureVertical方法里面的code

        mTotalLength = 0;        int maxWidth = 0;        int childState = 0;        int alternativeMaxWidth = 0;        int weightedMaxWidth = 0;        boolean allFillParent = true;        float totalWeight = 0;        final int count = getVirtualChildCount();        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);        boolean matchWidth = false;        boolean skippedMeasure = false;        final int baselineChildIndex = mBaselineAlignedChildIndex;                final boolean useLargestChild = mUseLargestChild;        int largestChildHeight = Integer.MIN_VALUE;        int consumedExcessSpace = 0;

这里主要是一些初始化的变量,在后面使用的时候我们再来具体讲解其作用

for (int i = 0; i < count; ++i) {    final View child = getVirtualChildAt(i);    if (child == null) {        mTotalLength += measureNullChild(i);        continue;    }    if (child.getVisibility() == View.GONE) {       i += getChildrenSkipCount(child, i);       continue;    }    if (hasDividerBeforeChildAt(i)) {        mTotalLength += mDividerHeight;    }    final LayoutParams lp = (LayoutParams) child.getLayoutParams();    totalWeight += lp.weight;    final boolean useExcessSpace = lp.height == 0 && lp.weight > 0;    if (heightMode == MeasureSpec.EXACTLY && useExcessSpace) {        // Optimization: don't bother measuring children who are only        // laid out using excess space. These views will get measured        // later if we have space to distribute.        final int totalLength = mTotalLength;        mTotalLength = Math.max(totalLength, totalLength + lp.topMargin + lp.bottomMargin);        skippedMeasure = true;    } else {        if (useExcessSpace) {            // The heightMode is either UNSPECIFIED or AT_MOST, and            // this child is only laid out using excess space. Measure            // using WRAP_CONTENT so that we can find out the view's            // optimal height. We'll restore the original height of 0            // after measurement.            lp.height = LayoutParams.WRAP_CONTENT;        }        // Determine how big this child would like to be. If this or        // previous children have given a weight, then we allow it to        // use all available space (and we will shrink things later        // if needed).        final int usedHeight = totalWeight == 0 ? mTotalLength : 0;        measureChildBeforeLayout(child, i, widthMeasureSpec, 0,                heightMeasureSpec, usedHeight);        final int childHeight = child.getMeasuredHeight();        if (useExcessSpace) {            // Restore the original height and record how much space            // we've allocated to excess-only children so that we can            // match the behavior of EXACTLY measurement.            lp.height = 0;            consumedExcessSpace += childHeight;        }        final int totalLength = mTotalLength;        mTotalLength = Math.max(totalLength, totalLength + childHeight + lp.topMargin +               lp.bottomMargin + getNextLocationOffset(child));        if (useLargestChild) {            largestChildHeight = Math.max(childHeight, largestChildHeight);        }    }    /**     * If applicable, compute the additional offset to the child's baseline     * we'll need later when asked {@link #getBaseline}.     */    if ((baselineChildIndex >= 0) && (baselineChildIndex == i + 1)) {       mBaselineChildTop = mTotalLength;    }    // if we are trying to use a child index for our baseline, the above    // book keeping only works if there are no children above it with    // weight.  fail fast to aid the developer.    if (i < baselineChildIndex && lp.weight > 0) {        throw new RuntimeException("A child of LinearLayout with index "                + "less than mBaselineAlignedChildIndex has weight > 0, which "                + "won't work.  Either remove the weight, or don't set "                + "mBaselineAlignedChildIndex.");    }    boolean matchWidthLocally = false;    if (widthMode != MeasureSpec.EXACTLY && lp.width == LayoutParams.MATCH_PARENT) {        // The width of the linear layout will scale, and at least one        // child said it wanted to match our width. Set a flag        // indicating that we need to remeasure at least that view when        // we know our width.        matchWidth = true;        matchWidthLocally = true;    }    final int margin = lp.leftMargin + lp.rightMargin;    final int measuredWidth = child.getMeasuredWidth() + margin;    maxWidth = Math.max(maxWidth, measuredWidth);    childState = combineMeasuredStates(childState, child.getMeasuredState());    allFillParent = allFillParent && lp.width == LayoutParams.MATCH_PARENT;    if (lp.weight > 0) {        /*         * Widths of weighted Views are bogus if we end up         * remeasuring, so keep them separate.         */        weightedMaxWidth = Math.max(weightedMaxWidth,                matchWidthLocally ? margin : measuredWidth);    } else {        alternativeMaxWidth = Math.max(alternativeMaxWidth,                matchWidthLocally ? margin : measuredWidth);    }    i += getChildrenSkipCount(child, i);}

1、13~15行是判断subchild之前是否有divider,如果有的话,计算divider的高度,divider可以通过设置android:divider属性
这里写图片描述
2、21~29行判断subchild当height为0并且有设置weight大小时,用useExcessSpace来表示true/false,可理解为 是否要使用LinearLayout余下的空间,当linearLayout大小确定时,我们选择跳过该subchild的测量,等到后面通过weight来计算subchild的大小;当linearLayout大小不确定时,30~37的lp.height = LayoutParams.WRAP_CONTENT这样做是为了后面紧接着的测量用的,测量该subchild的内容应该的大小
3、44行的measureChildBeforeLayout方法是测量subchild大小的
4、48~54行,当subchild被测量并且有设置weight大小,此时用consumedExcessSpace 来保存所有这样的subchild的高的总和
5、60~62行找出所有subchild里面height的value最大的
6、83~110这之间主要是为了找出subchild中width最大的value,以给最后的LinearLayout自己测量用的

if (useLargestChild &&        (heightMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.UNSPECIFIED)) {    mTotalLength = 0;    for (int i = 0; i < count; ++i) {        final View child = getVirtualChildAt(i);        if (child == null) {            mTotalLength += measureNullChild(i);            continue;        }        if (child.getVisibility() == GONE) {            i += getChildrenSkipCount(child, i);            continue;        }        final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)                child.getLayoutParams();        // Account for negative margins        final int totalLength = mTotalLength;        mTotalLength = Math.max(totalLength, totalLength + largestChildHeight +                lp.topMargin + lp.bottomMargin + getNextLocationOffset(child));    }}
假如1~2行的条件满足的话,直接看组后21~22行,此时LinearLayout会把每一个subchild的height都当成是largestChildHeight 来统计
// Add in our paddingmTotalLength += mPaddingTop + mPaddingBottom;int heightSize = mTotalLength;// Check against our minimum heightheightSize = Math.max(heightSize, getSuggestedMinimumHeight());// Reconcile our calculated size with the heightMeasureSpecint heightSizeAndState = resolveSizeAndState(heightSize, heightMeasureSpec, 0);heightSize = heightSizeAndState & MEASURED_SIZE_MASK;// Either expand children with weight to take up available space or// shrink them if they extend beyond our current bounds. If we skipped// measurement on any children, we need to measure them now.int remainingExcess = heightSize - mTotalLength        + (mAllowInconsistentMeasurement ? 0 : consumedExcessSpace);
 上面几行是计算LinearLayout的height大小的,最后16~17行计算所有subchild之外,LinearLayout剩余的未使用的垂直方向的空间大小。
if (skippedMeasure || remainingExcess != 0 && totalWeight > 0.0f) {    float remainingWeightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;    mTotalLength = 0;    for (int i = 0; i < count; ++i) {        final View child = getVirtualChildAt(i);        if (child == null || child.getVisibility() == View.GONE) {            continue;        }        final LayoutParams lp = (LayoutParams) child.getLayoutParams();        final float childWeight = lp.weight;        if (childWeight > 0) {            final int share = (int) (childWeight * remainingExcess / remainingWeightSum);            remainingExcess -= share;            remainingWeightSum -= childWeight;            final int childHeight;            if (mUseLargestChild && heightMode != MeasureSpec.EXACTLY) {                childHeight = largestChildHeight;            } else if (lp.height == 0 && (!mAllowInconsistentMeasurement                    || heightMode == MeasureSpec.EXACTLY)) {                // This child needs to be laid out from scratch using                // only its share of excess space.                childHeight = share;            } else {                // This child had some intrinsic height to which we                // need to add its share of excess space.                childHeight = child.getMeasuredHeight() + share;            }            final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(                    Math.max(0, childHeight), MeasureSpec.EXACTLY);            final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,                    mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin,                    lp.width);            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);            // Child may now not fit in vertical dimension.            childState = combineMeasuredStates(childState, child.getMeasuredState()                    & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));        }        final int margin =  lp.leftMargin + lp.rightMargin;        final int measuredWidth = child.getMeasuredWidth() + margin;        maxWidth = Math.max(maxWidth, measuredWidth);        boolean matchWidthLocally = widthMode != MeasureSpec.EXACTLY &&                lp.width == LayoutParams.MATCH_PARENT;        alternativeMaxWidth = Math.max(alternativeMaxWidth,                matchWidthLocally ? margin : measuredWidth);        allFillParent = allFillParent && lp.width == LayoutParams.MATCH_PARENT;        final int totalLength = mTotalLength;        mTotalLength = Math.max(totalLength, totalLength + child.getMeasuredHeight() +                lp.topMargin + lp.bottomMargin + getNextLocationOffset(child));    }    // Add in our padding    mTotalLength += mPaddingTop + mPaddingBottom;    // TODO: Should we recompute the heightSpec based on the new total length?} else {

1、上面的if-else满足的添加是之前有subchild有跳过测量,或者是有sunchild设置了weight的值并且LinearLayout垂直方向的空间没有被使用完。
2、这里需要注意的是,假如一共有3个subchild且都有设置weight ,分别为3、2、1,我们假设剩余的space为120,则第一个view的大小为120 * 3/(3+2+1)=60,第二个view的大小为(120-60)*2/(2+1)=40,第3个view的大小为(60-40)*1/1 = 20
3、上面其余的code就不多解释了,通过前面code的分析这里因该可以看的明白

else {    alternativeMaxWidth = Math.max(alternativeMaxWidth,                                   weightedMaxWidth);    // We have no limit, so make all weighted views as tall as the largest child.    // Children will have already been measured once.    if (useLargestChild && heightMode != MeasureSpec.EXACTLY) {        for (int i = 0; i < count; i++) {            final View child = getVirtualChildAt(i);            if (child == null || child.getVisibility() == View.GONE) {                continue;            }            final LinearLayout.LayoutParams lp =                    (LinearLayout.LayoutParams) child.getLayoutParams();            float childExtra = lp.weight;            if (childExtra > 0) {                child.measure(                        MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(),                                MeasureSpec.EXACTLY),                        MeasureSpec.makeMeasureSpec(largestChildHeight,                                MeasureSpec.EXACTLY));            }        }    }}

这一段code就不分析了,都很简单

setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),        heightSizeAndState);if (matchWidth) {    forceUniformWidth(count, heightMeasureSpec);}

最后,设置LinearLayout的size大小和状态,如果LinearLayout有设置width为match_parent的话,将会调用forceUniformWidth再测量一次所有的subchild,这里主要是测量subchild的width大小

下面我们继续分析LayoutVertical方法

void layoutVertical(int left, int top, int right, int bottom) {        final int paddingLeft = mPaddingLeft;        int childTop;        int childLeft;        // Where right end of child should go        final int width = right - left;        int childRight = width - mPaddingRight;        // Space available for child        int childSpace = width - paddingLeft - mPaddingRight;        final int count = getVirtualChildCount();        final int majorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;        final int minorGravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;        switch (majorGravity) {           case Gravity.BOTTOM:               // mTotalLength contains the padding already               childTop = mPaddingTop + bottom - top - mTotalLength;               break;               // mTotalLength contains the padding already           case Gravity.CENTER_VERTICAL:               childTop = mPaddingTop + (bottom - top - mTotalLength) / 2;               break;           case Gravity.TOP:           default:               childTop = mPaddingTop;               break;        }        for (int i = 0; i < count; i++) {            final View child = getVirtualChildAt(i);            if (child == null) {                childTop += measureNullChild(i);            } else if (child.getVisibility() != GONE) {                final int childWidth = child.getMeasuredWidth();                final int childHeight = child.getMeasuredHeight();                final LinearLayout.LayoutParams lp =                        (LinearLayout.LayoutParams) child.getLayoutParams();                int gravity = lp.gravity;                if (gravity < 0) {                    gravity = minorGravity;                }                final int layoutDirection = getLayoutDirection();                final int absoluteGravity = Gravity.getAbsoluteGravity(gravity, layoutDirection);                switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {                    case Gravity.CENTER_HORIZONTAL:                        childLeft = paddingLeft + ((childSpace - childWidth) / 2)                                + lp.leftMargin - lp.rightMargin;                        break;                    case Gravity.RIGHT:                        childLeft = childRight - childWidth - lp.rightMargin;                        break;                    case Gravity.LEFT:                    default:                        childLeft = paddingLeft + lp.leftMargin;                        break;                }                if (hasDividerBeforeChildAt(i)) {                    childTop += mDividerHeight;                }                childTop += lp.topMargin;                setChildFrame(child, childLeft, childTop + getLocationOffset(child),                        childWidth, childHeight);                childTop += childHeight + lp.bottomMargin + getNextLocationOffset(child);                i += getChildrenSkipCount(child, i);            }        }    }

上面的code的大体功能如下:
1、LinearLayout里面所有的subChild作为一个整体,判断是处于LinearLayout的top、bottom还是center_vertical
2、循环遍历subChild来设置child在LinearLayout中的位置,code很简单,细心看很容易明白
3、setChildFrame方法最终是调用了child.layout 方法

ok,关于LienarLayout方面的分析到此结束!

0 0
原创粉丝点击