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

现在剩下Framelayout了;
直接先看onlayout:

 @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        layoutChildren(left, top, right, bottom, false /* no force left gravity */);
    }

直接执行的是` 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);
            }
        }
    }

从上面代码不难看出,布局的时候,子组件之间都是共享容器的空间;因为每次计算子组件的位置的时候,都是以容器的左右上下边界来为基础,然后加上或者减去子组件本身的左右上下边距;所以Framelayout里面的组件都是一层一层堆叠的,并不存在互相拥挤的情况。
到此为止,我们通过源码分析出了Linearlayout,Relativelayout,Framelayout的布局区别。大家有兴趣的话可以再看看别的布局源码;也可以自己模仿这些自定义一个自己的ViewGroup容器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值