父布局为RelativeLayout,且固定高度,设置gravity="center_vertical"无效的问题

 首先看下布局情况,一个RelativeLayout的父布局里有三个直接子元素,两个RelativeLayout布局和一个TextView控件;

 <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center_vertical">

            <RelativeLayout
                android:id="@+id/rlayout_left"
                android:layout_width="50dp"
                android:layout_height="match_parent">

                <ImageView
                    android:layout_width="23dp"
                    android:layout_height="23dp"
                    android:layout_centerInParent="true"
                    android:background="@drawable/ic_default_head_img"
                    android:scaleType="centerCrop" />

            </RelativeLayout>

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_toRightOf="@+id/rlayout_left"
                android:text="用户登录" />

            <RelativeLayout
                android:layout_width="50dp"
                android:layout_height="match_parent"
                android:layout_alignParentRight="true">

                <ImageView
                    android:layout_width="16dp"
                    android:layout_height="16dp"
                    android:layout_centerInParent="true"
                    app:srcCompat="@drawable/ic_close" />

            </RelativeLayout>

        </RelativeLayout>

       父布局的RelativeLayout设置了android:gravity="center_vertical"属性,但是其中的TextView控件并没有垂直居中,如果把里

面的两个RelativeLayout布局都去掉,或者将它们的高度都设置android:layout_height="wrap_content",也就是不充满父布局

,这样的情况下TextView控件就垂直居中了,也就是说父布局的RelativeLayout的android:gravity="center_vertical"属性生效了;

遇到这种情况可以对TextView设置android:layout_centerVertical="true"属性,使其垂直居中。

 

       这个问题,本质上其实是,如果子控件高度不一样 或者有一个控件较其它的控件高,则会影响其它子控件的垂直居中处理,

我们可以从RelativeLayout布局类的源码中窥探一二。可以看到centerVertical()方法中确定的top高度,最终各子控件的排列布局

会以这个值为准;同理,水平居中使用android:gravity="center_horizontal",应该也有同样的问题。

public class RelativeLayout extends ViewGroup {

    …………………省略………………………

   @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    …………………省略………………………
        for (int i = 0; i < count; i++) {
            final View child = views[i];
            if (child.getVisibility() != GONE) {
                final LayoutParams params = (LayoutParams) child.getLayoutParams();

                applyVerticalSizeRules(params, myHeight, child.getBaseline());
                measureChild(child, params, myWidth, myHeight);
                if (positionChildVertical(child, params, myHeight, isWrapContentHeight)) {
                    offsetVerticalAxis = true;
                }

                if (isWrapContentWidth) {
                    if (isLayoutRtl()) {
                        if (targetSdkVersion < Build.VERSION_CODES.KITKAT) {
                            width = Math.max(width, myWidth - params.mLeft);
                        } else {
                            width = Math.max(width, myWidth - params.mLeft + params.leftMargin);
                        }
                    } else {
                        if (targetSdkVersion < Build.VERSION_CODES.KITKAT) {
                            width = Math.max(width, params.mRight);
                        } else {
                            width = Math.max(width, params.mRight + params.rightMargin);
                        }
                    }
                }

                if (isWrapContentHeight) {
                    if (targetSdkVersion < Build.VERSION_CODES.KITKAT) {
                        height = Math.max(height, params.mBottom);
                    } else {
                        height = Math.max(height, params.mBottom + params.bottomMargin);
                    }
                }

                if (child != ignore || verticalGravity) {
                    left = Math.min(left, params.mLeft - params.leftMargin);
                    top = Math.min(top, params.mTop - params.topMargin);
                }

                if (child != ignore || horizontalGravity) {
                    right = Math.max(right, params.mRight + params.rightMargin);
                    bottom = Math.max(bottom, params.mBottom + params.bottomMargin);
                }
            }
        }
    …………………省略………………………
}

    private boolean positionChildVertical(View child, LayoutParams params, int myHeight,
            boolean wrapContent) {

        int[] rules = params.getRules();

        if (params.mTop == VALUE_NOT_SET && params.mBottom != VALUE_NOT_SET) {
            // Bottom is fixed, but top varies
            params.mTop = params.mBottom - child.getMeasuredHeight();
        } else if (params.mTop != VALUE_NOT_SET && params.mBottom == VALUE_NOT_SET) {
            // Top is fixed, but bottom varies
            params.mBottom = params.mTop + child.getMeasuredHeight();
        } else if (params.mTop == VALUE_NOT_SET && params.mBottom == VALUE_NOT_SET) {
            // Both top and bottom vary
            if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) {
                if (!wrapContent) {
                    centerVertical(child, params, myHeight);
                } else {
                    params.mTop = mPaddingTop + params.topMargin;
                    params.mBottom = params.mTop + child.getMeasuredHeight();
                }
                return true;
            } else {
                params.mTop = mPaddingTop + params.topMargin;
                params.mBottom = params.mTop + child.getMeasuredHeight();
            }
        }
        return rules[ALIGN_PARENT_BOTTOM] != 0;
    }

private static void centerHorizontal(View child, LayoutParams params, int myWidth) {
        int childWidth = child.getMeasuredWidth();
        int left = (myWidth - childWidth) / 2;

        params.mLeft = left;
        params.mRight = left + childWidth;
    }

    private static void centerVertical(View child, LayoutParams params, int myHeight) {
        int childHeight = child.getMeasuredHeight();
        int top = (myHeight - childHeight) / 2;

        params.mTop = top;
        params.mBottom = top + childHeight;
    }

    @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);
            }
        }
    }

…………………省略………………………
}

 

 

由于作者水平有限,语言描述及代码实现中难免有纰漏,望各位看官多提宝贵意见!

Hello , World !

感谢所有!

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

windfallsheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值