自定义 ViewGroup(一)

来源:互联网 发布:借壳上市案例分析 知乎 编辑:程序博客网 时间:2024/05/01 04:23

ViewGroup是View的子类,但是它可以管理多个View,ViewGroup相当于一个放置View的容器。

每个ViewGroup在管理内部的childView时都需要有一个LayoutParams,用于确定childView支持哪些属性,比如LinearLayout指定LinearLayout.LayoutParams等。

View在ViewGroup中会根据测量模式和ViewGroup给出的建议宽和高,计算出自己的宽和高;同时
还要在ViewGroup为其指定的区域内绘制自己的形态。

ViewGroup在布置其中的childView时要经过onMeasure方法来测量其中的子视图大小,然后经过o
nLayout来指定childView的区域。

ViewGroup会为childView指定测量模式,下面简单介绍下

三种测量模式:

1、EXACTLY:表示设置了精确的值,一般当childView设置其宽、高为精确值、match_parent
时,ViewGroup会将其设置为EXACTLY;
2、AT_MOST:表示子布局被限制在一个最大值内,一般当childView设置其宽、高为wrap_content时
,ViewGroup会将其设置为AT_MOST;
3、UNSPECIFIED:表示子布局想要多大就多大,一般出现在AadapterView的item的heightMode中
、ScrollView的childView的heightMode中;此种模式比较少见。

1、onMeasure:在onMeasure的测量值以及模式,以及设置自己的宽和高:

/** * 计算所有ChildView的宽度和高度然后根据ChildView的计算结果,设置自己的宽和高 */@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){    /**    * 获得此ViewGroup上级容器为其推荐的宽和高,以及计算模式    */    int widthMode = MeasureSpec.getMode(widthMeasureSpec);    int heightMode = MeasureSpec.getMode(heightMeasureSpec);    int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);    int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);    //根据各个childView的宽高以及当前ViewGroup的参考宽高计算要设置的宽高    ...    ...    //设置当前ViewGroup的宽高    setMeasuredDimension(width,height);}

2、onLayout对其所有childView进行定位(设置childView的绘制区域)

@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b){    int cCount = getChildCount();    for (int i = 0; i < cCount; i++){        View childView = getChildAt(i);        cWidth = childView.getMeasuredWidth();        cHeight = childView.getMeasuredHeight();        cParams = (MarginLayoutParams)childView.getLayoutParams();        //做其他的计算        ...        //布置childView        childView.layout(cl, ct, cr, cb);    }}//举个栗子@Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        //该容器布置自视图时触发        int count = getChildCount();        //前面的总高度        int preHeight = 0;        for (int i = 0; i < count; i++) {            View child = getChildAt(i);            if (child.getVisibility() == View.GONE) {                continue;            }            //布局孩子(left,top,right,bottom)            child.layout(0, preHeight, child.getMeasuredWidth(),                     preHeight + child.getMeasuredHeight());            preHeight += child.getMeasuredHeight();        }    }

针对ViewGroup所支持的LayoutParam,可以通过重写generateLayoutParams方法来指定,不指定则默认为ViewGroup.LayoutParam。指定方式如下:(如设置能够支持margin)

@Overridepublic LayoutParams generateLayoutParams(AttributeSet attrs) {    return new MarginLayoutParams(getContext(),attrs);}
原创粉丝点击