android 自定义组视图布局不正确

android Custom group view doesn't lay out correctly

我创建了这个自定义视图组:

public class CustomGroupView extends ViewGroup {

    public static final String TAG = "CustomGroupView";

    public CustomGroupView(Context context) {
        this(context, null);
    }

    public CustomGroupView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomGroupView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.d(TAG, "onMeasure");

        int childrenCount = getChildCount();

        // measure all children
        for(int i=0; i<childrenCount; i++) {
            final View child = getChildAt(i);
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
        }

        // the height and the width of the overall group view is
        // the height and the width of the last child
        View lastChild = getChildAt(childrenCount-1);
        int overallHeight = lastChild.getMeasuredHeight();
        int overallWidth = lastChild.getMeasuredWidth();

        Log.d(TAG, "overallHeight: " + overallHeight + "; overallWidth: " + overallWidth);

        setMeasuredDimension(resolveSize(overallWidth, widthMeasureSpec), resolveSize(overallHeight, heightMeasureSpec));
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        Log.d(TAG, "onLayout");

        Log.d(TAG, "left: " + left + "; top: " + top + "; right: " + right + "; bottom: " + bottom);

        int childrenCount = getChildCount();

        // all children will be aligned to the top
        for(int i=0; i<childrenCount; i++) {
            final View child = getChildAt(i);

            int childLeft = left;
            int childTop = top;
            int childRight = left + child.getMeasuredWidth();
            int childBottom = top + child.getMeasuredHeight();

            Log.d("TAG", "child #: " + i + "; left: " + childLeft + "; top: " + childTop + "; right: " + childRight +"; bottom: " + childBottom);

            child.layout(childLeft, childTop, childRight, childBottom);
        }
    }
}

我发现当我将它放入 LinearLayout 容器时它的行为很奇怪。
正确工作时的示例:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <org.test.oct9customgroup.CustomGroupView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:alpha="1"
            android:background="#4c4c4c"
            android:scaleX="0.6"
            android:padding="8dp"
            android:text="1"
            android:textSize="32sp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:alpha="0.7"
            android:background="#ffffa3"
            android:scaleX="0.75"
            android:padding="8dp"
            android:text="2"
            android:textSize="32sp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:alpha="0.7"
            android:background="#fce5e8"
            android:scaleX="0.9"
            android:padding="8dp"
            android:text="3"
            android:textSize="32sp"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:alpha="0.4"
            android:background="#b3ffc3"
            android:padding="32dp"
            android:text="Last child's text"
            android:textSize="32sp"/>

    </org.test.oct9customgroup.CustomGroupView>

    <TextView
        android:id="@+id/top_textview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="50sp"
        android:background="#CCCCCC"
        android:text="Top text"/>

</LinearLayout>

但是如果我更改自定义视图组和文本视图的顺序:

<LinearLayout>

    <TextView/>

    <org.test.oct9customgroup.CustomGroupView>
        <TextView/>
        <TextView/>
        <TextView/>
        <TextView/>
    </org.test.oct9customgroup.CustomGroupView>

</LinearLayout>

问题:那个文本视图和我的组视图之间出现了很大的差距,我不知道如何摆脱它。

图片和日志:

一切正常时记录:

10-09 15:54:08.922 18046-18046/org.test.viewsexperiments D/CustomGroupView: onMeasure
10-09 15:54:08.922 18046-18046/org.test.viewsexperiments D/CustomGroupView: overallHeight: 144; overallWidth: 800
10-09 15:54:08.924 18046-18046/org.test.viewsexperiments D/CustomGroupView: onLayout
10-09 15:54:08.925 18046-18046/org.test.viewsexperiments D/CustomGroupView: left: 0; top: 0; right: 800; bottom: 144
10-09 15:54:08.925 18046-18046/org.test.viewsexperiments D/CustomGroupView: child #: 0; left: 0; top: 0; right: 800; bottom: 80
10-09 15:54:08.926 18046-18046/org.test.viewsexperiments D/CustomGroupView: child #: 1; left: 0; top: 0; right: 800; bottom: 80
10-09 15:54:08.926 18046-18046/org.test.viewsexperiments D/CustomGroupView: child #: 2; left: 0; top: 0; right: 800; bottom: 80
10-09 15:54:08.926 18046-18046/org.test.viewsexperiments D/CustomGroupView: child #: 3; left: 0; top: 0; right: 800; bottom: 144

出现间隙时记录:

10-09 15:59:24.202 27506-27506/? D/CustomGroupView: onMeasure
10-09 15:59:24.202 27506-27506/? D/CustomGroupView: overallHeight: 144; overallWidth: 800
10-09 15:59:24.203 27506-27506/? D/CustomGroupView: onLayout
10-09 15:59:24.204 27506-27506/? D/CustomGroupView: left: 0; top: 90; right: 800; bottom: 234
10-09 15:59:24.204 27506-27506/? D/CustomGroupView: child #: 0; left: 0; top: 90; right: 800; bottom: 170
10-09 15:59:24.204 27506-27506/? D/CustomGroupView: child #: 1; left: 0; top: 90; right: 800; bottom: 170
10-09 15:59:24.204 27506-27506/? D/CustomGroupView: child #: 2; left: 0; top: 90; right: 800; bottom: 170
10-09 15:59:24.205 27506-27506/? D/CustomGroupView: child #: 3; left: 0; top: 90; right: 800; bottom: 234


你能告诉我为什么会这样吗?

编辑 结果发现间隙的高度等于我自定义组视图上方的TextView的高度。

我想在我的自定义组视图的 canvas 子级上绘图时会发生一些变化。
可能绘图应该从 (0, 0) 开始,但它从 (0, top) 点开始。

有没有人知道如何解决它?

编辑2添加红色背景后

<org.test.oct9customgroup.CustomGroupView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#ff0000"> 

protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

这四个位置是 CustomGroupView 与其父级之间的距离,因此在布置子级时使用它们没有任何意义。代码应该是:

int childLeft = 0;
int childTop = 0;
int childRight = childLeft + child.getMeasuredWidth();
int childBottom = childTop + child.getMeasuredHeight();

ViewGroup 由其父级正确布局。错误是你需要

int childTop = 0;

而不是

int childTop = top;

在你的 onLayout 中。 onLayout提供的四个值都是相对于parent