首先看下布局情况,一个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 !
感谢所有!