Android应用开发原理之从源码分析看Linearlayout、Relativelayout,Framelayout的布局差别(Relativelayout分析)

前面说过Linearlayout,现在研究下Relativelayout的排版源码实现;
首先还是找到onlayout源码:

@Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        //  The layout has actually already been performed and the positions
        //  cached.  Apply the cached values to the children.
        final int count = getChildCount();

        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                RelativeLayout.LayoutParams st =
                        (RelativeLayout.LayoutParams) child.getLayoutParams();
                child.layout(st.mLeft, st.mTop, st.mRight, st.mBottom);
            }
        }
    }

发现不对,因为这个里面貌似没有做关于排版子位置的逻辑;现在在仔细想想,Relativelayout确实没有对子布局做什么排版。所以的相对位置貌似都是在子组件中进行设置的;好,那么仔细想想,子组件对相对位置的排版貌似影响着子组件的本身大小;
现在确认了,那么一定是在计算子组件大小之前对子组件的相对位置进行了处理。好了,我们知道是在onMeasure里面进行计算子组件大小的;现在我们看这个方法:
部分代码片段:

..........
 applyHorizontalSizeRules(params, myWidth, rules);
 measureChildHorizontal(child, params, myWidth, myHeight);
..........
applyVerticalSizeRules(params, myHeight);
measureChild(child, params, myWidth, myHeight);

先分析这两队方法:

 private void applyHorizontalSizeRules(LayoutParams childParams, int myWidth, int[] rules) {
        RelativeLayout.LayoutParams anchorParams;
        //设置初始值
        childParams.mLeft = VALUE_NOT_SET;
        childParams.mRight = VALUE_NOT_SET;
        //获取layout_toLeftOf属性
        anchorParams = getRelatedViewParams(rules, LEFT_OF);
        if (anchorParams != null) {
        //假设组件B设置为在组件A的左边;那么B的右边界=A的左边界-A左内边距-B右内边距;这个逻辑关系大家在纸上画一下就好;
            childParams.mRight = anchorParams.mLeft - (anchorParams.leftMargin +
                    childParams.rightMargin);
        } else if (childParams.alignWithParent && rules[LEFT_OF] != 0) {
            if (myWidth >= 0) {
            //得出组件的右边界
                childParams.mRight = myWidth - mPaddingRight - childParams.rightMargin;
            }
        }
        //同样,得到android:layout_toRightOf属性
        anchorParams = getRelatedViewParams(rules, RIGHT_OF);
        if (anchorParams != null) {
        //自己分析。。。
            childParams.mLeft = anchorParams.mRight + (anchorParams.rightMargin +
                    childParams.leftMargin);
        } else if (childParams.alignWithParent && rules[RIGHT_OF] != 0) {
            childParams.mLeft = mPaddingLeft + childParams.leftMargin;
        }
         //得到android:layout_alignLeft属性
        anchorParams = getRelatedViewParams(rules, ALIGN_LEFT);
        if (anchorParams != null) {
        //进行左对齐操作
            childParams.mLeft = anchorParams.mLeft + childParams.leftMargin;
        } else if (childParams.alignWithParent && rules[ALIGN_LEFT] != 0) {
            childParams.mLeft = mPaddingLeft + childParams.leftMargin;
        }
        //得到android:layout_alignRight属性
        anchorParams = getRelatedViewParams(rules, ALIGN_RIGHT);
        if (anchorParams != null) {
        //进行右对齐操作
            childParams.mRight = anchorParams.mRight - childParams.rightMargin;
        } else if (childParams.alignWithParent && rules[ALIGN_RIGHT] != 0) {
            if (myWidth >= 0) {
                childParams.mRight = myWidth - mPaddingRight - childParams.rightMargin;
            }
        }
        //对android:layout_alignParentLeft进行处理,即将自己置于父容器的左边
        if (0 != rules[ALIGN_PARENT_LEFT]) {
            childParams.mLeft = mPaddingLeft + childParams.leftMargin;
        }
        //将自己置于父容器的右边
        if (0 != rules[ALIGN_PARENT_RIGHT]) {
            if (myWidth >= 0) {
                childParams.mRight = myWidth - mPaddingRight - childParams.rightMargin;
            }
        }
    }

看完了这段代码;大概就知道这个方法是计算组件左边界和右边界的值了;
因此也就知道
applyVerticalSizeRules(params, myHeight);
可能是计算组件顶部和底部边界的方法了。这里就不在分析了。因为逻辑和上面的差不多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值