LinearLayout 中的 gravity 属性

在android UI布局中,有android:gravity 和 android:layout_gravity 两个属性可以设置控件的位置。在 LinearLayout 中,这两种属性的使用与其他布局稍有不同,在这里记下来。

在 LinearLayout 中,这两种属性的使用与 LinearLayout 的 android:orientation 属性有关。


附上源码(以 vertical 为例):


 /**
     * Position the children during a layout pass if the orientation of this
     * LinearLayout is set to {@link #VERTICAL}.
     *
     * @see #getOrientation()
     * @see #setOrientation(int)
     * @see #onLayout(boolean, int, int, int, int)
     */
    void layoutVertical() {
        final int paddingLeft = mPaddingLeft;

        int childTop = mPaddingTop;
        int childLeft;
        
        // Where right end of child should go
        final int width = mRight - mLeft;
        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.HORIZONTAL_GRAVITY_MASK;

        if (majorGravity != Gravity.TOP) {
           switch (majorGravity) {
               case Gravity.BOTTOM:
                   // mTotalLength contains the padding already, we add the top
                   // padding to compensate
                   childTop = mBottom - mTop + mPaddingTop - mTotalLength;
                   break;

               case Gravity.CENTER_VERTICAL:
                   childTop += ((mBottom - mTop)  - mTotalLength) / 2;
                   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;
                }
                
                switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                    case Gravity.LEFT:
                        childLeft = paddingLeft + lp.leftMargin;
                        break;

                    case Gravity.CENTER_HORIZONTAL:
                        childLeft = paddingLeft + ((childSpace - childWidth) / 2)
                                + lp.leftMargin - lp.rightMargin;
                        break;

                    case Gravity.RIGHT:
                        childLeft = childRight - childWidth - lp.rightMargin;
                        break;
                    default:
                        childLeft = paddingLeft;
                        break;
                }
                
                
                childTop += lp.topMargin;
                setChildFrame(child, childLeft, childTop + getLocationOffset(child),
                        childWidth, childHeight);
                childTop += childHeight + lp.bottomMargin + getNextLocationOffset(child);

                i += getChildrenSkipCount(child, i);
            }
        }
    }


在以上源码中,mGravity 表示 LinearLayout 自身的 android:gravity 属性, majorGravity 和 minorGravity 由 mGravity 分别与  Gravity.VERTICAL_GRAVITY_MASK 和Gravity.HORIZONTAL_GRAVITY_MASK 做位与运算而来,应该是确定 mGravity 是垂直方向上还是水平方向上的属性值。

在布局过程中,先考虑 majorGravity, 如果它是垂直方向上的属性(与 orientation 一致),生效,否则无效。

之后考虑每个子视图自身的 android:layout_gravity 属性值,即代码中的 lp.gravity。从代码中可以看出,如果 lp.gravity 大于0, 就是说该子视图设置了 android:layout_gravity 属性,那么就使用它自己设置的,否则使用 minorGravity。然后判断得出的 gravity 是不是 水平方向上的(与 orientation 不一致的方向),如果是,生效,不是,直接无视。


由此,我们可以得出结论:

1. LinearLayout 自身的 android:gravity 属性可以设为任意 gravity 值,与其 orientation 方向一致的属性必然生效;不一致的属性可能生效,也可能不生效。不生效是被子视图自身的 android:layout_gravity 属性覆盖掉了。

2. 作为 LinearLayout 子视图的控件,它们的 android:layout_gravity 属性只有设成和 LinearLayout 的 orientation 不一致的属性的时候,才可以生效,否则不生效。并且,如果生效,是可以覆盖掉 LinearLayout 自身的 android:gravity 属性值带来的效果的(如果是同一方向上的属性的话)。


之前发的那篇写的不对,在这里向大家道歉,希望大家原谅!

这篇感觉对了,当然如果有问题的话,还请各位指教!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值