ViewGroup中的onLayout方法的理解

今天在自定义一个ViewGroup的时候出现了一个这样问题,事后分析是因为自己对ViewGroup中的onLayout方法和其中子View的layout方法的理解不足导致的。

我要实现的效果是做一个类似LinearLayout垂直排列子View的ViewGroup,在ViewGroup中onMeasure方法中测量完ViewGroup的大小以后进开始摆放子View了,onLayout的开始的代码如下:

@Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        int count = getChildCount();
        int curHeight = top;
        for (int i = 0 ; i < count ; i++){
            View childView = getChildAt(i);
            int height = childView.getMeasuredHeight();
            int width = childView.getMeasuredWidth();
            childView.layout(left,curHeight,right + width,bottom + height);

            curHeight += height;
        }
    }

代码如下,测试了一下发现当自定义的ViewGroup和其他的View并列的时候就会出现问题,如果子布局中只有自定义的ViewGroup自己,页面显示是没有问题的。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <Button
    	android:background="#e41212"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:text="按钮"
        />

    <!--自定义ViewGroup-->
    <com.emm.datastructure.custom_view.ZHViewGroup
        android:background="#b42666"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:text="btn"
            />
    </com.emm.datastructure.custom_view.ZHViewGroup>

</LinearLayout>

经过分析发现是ViewGroup中的onLayout代码写错了,正确的onLayout方法如下:

/**
     *参数左上右下,是指以屏幕的左上角为坐标原点的坐标
     */
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        int count = getChildCount();
        //记录当前高度位置。
        //因为在摆放子View的时候,子View的layout方法是以ViewGroup的左上角为坐标原点来测量的,所以第一个子View的高度应该为0。
        int curHeight = 0; //注意此处和上面错误的不一样
        for (int i = 0 ; i < count ; i++){
            View childView = getChildAt(i);
            int height = childView.getMeasuredHeight();
            int width = childView.getMeasuredWidth();
            childView.layout(left,curHeight,right + width,bottom + height);

            curHeight += height;
        }
    }

上面的注释写的很清楚,是因为对ViewGroup中onLayout方法中的参数理解错误导致的,如果此处curHeight字段填写top参数,那么ViewGroup中的第一个子View肯定会向下移动上面并列的View的高度。

参考文章:自定义View,有这一篇就够了

猜你喜欢

转载自blog.csdn.net/static_zh/article/details/84647171