LinearLayout的横向和纵向布局问题

简介

  • 问题
  • LinearLayout的orientation属性
  • LinearLayout的layout_gravity属性
  • LinearLayout使用"orientation=horizontal/vertical",结合child view使用layout_gravity的各种情况的表现。
  • 问题解答

问题:在使用LinearLayout的orientation=horizontal时,使用layout_gravity="center"子布局只是纵向居中,并没有横向居中。

LinearLayout的orientation属性

LinearLayout的布局方式有两种,即由orientation属性控制,默认orientation=horizontal。在使用as作为开发工具的时候,如果在LinearLayout中出现多于两个的同级子布局时,as会强制要求设置显示设置orientation属性。

orientation属性的值有两个:horizontal和vertical
分别表示横向和纵向排列。

LinearLayout的layout_gravity属性

layout_gravity属性只有根布局是LinearLayout的情况下才能使用。表示子布局在父布局中的显示方式。

layout_gravity有以下几种值:
center:居中(横向和纵向均居中)
center_horizontal:水平居中
center_vertical:垂直居中
以上都是常用的属性,还有一些其他不常用的属性,就不再赘述(clip_horizontal、clip_vertical、end、start、left、right…)。

LinearLayout使用"orientation=horizontal/vertical",结合child view使用layout_gravity的各种情况的表现。

两种情况:
1、orientation=horizontal
子布局只能垂直方向的设置有效,不会水平方向的设置有效。
如果设置layout_gravity=center时,只有垂直方向的设置有效,水平方向的设置无效。
2、orientation=vertical
子布局只能水平方向的设置有效,不会垂直方向的设置有效。
如果设置layout_gravity=center时,只有水平方向的设置有效,垂直方向的设置无效。

解答

在查看LinearLayout的源码的时候会发现,LinearLayout在测量横向和纵向的布局时,有两个方法分别为layoutVertical()和layoutHorizontal()分别用于测量横向和纵向的布局位置。
我们就其中的一个方法进行解释:
layoutVertical():

void layoutVertical(int left, int top, int right, int bottom) {
    /**
      * 省略
      */
    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);
        }
    }
}

在for循环中仅仅是判断了CENTER_HORIZONTAL、RIGHT、LEFT三中情况,即在orientation=vertical时,只有水平居中和居左和居右有效,因此这就是为什么我们在设置layout_gravity=center时,只有水平方向的设置有效果了。
同理layoutHorizontal()方法也是同样的设置。

你可能感兴趣的:(LinearLayout的横向和纵向布局问题)