android自定义组视图没有正确布局

时间:2015-10-09 13:14:02

标签: android android-layout android-custom-view

我已创建此自定义视图组:

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>

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

<LinearLayout>

    <TextView/>

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

</LinearLayout>

问题:在该textview和我的群组视图之间出现了很大的差距,我不知道如何摆脱它。

图像和日志:

当一切正常时记录:

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

works correctly gap appears
你能告诉我为什么会这样吗?

编辑事实证明,间隙的高度等于TextView的高度,该高度高于我的自定义组视图。

我想在我的自定义组视图的画布上绘制时会有一些变化。
可能绘制应该从(0,0)开始,但它从(0,顶部)点开始。

有没有人有任何想法如何解决它?

编辑2 添加红色背景后

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

with red background

2 个答案:

答案 0 :(得分:2)

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

int childTop = 0;

而不是

int childTop = top;

onLayout中。 onLayout提供的四个值是相对于父

答案 1 :(得分:1)

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();