浅写重写ViewGroup和View(未完)

来源:互联网 发布:网络歌手麦子 编辑:程序博客网 时间:2024/04/23 14:37


在自定义控件中,可以重新定义android没有个控件。继承VIew或者ViewGroup。


一. 重写View:

1.测量
 onMeasure(int widthMeasureSpec, int heightMeasureSpec) ;在这个函数中测量控件的大小。
MeasureSpec类是个32位int。高2位了Mode,低30位是具体宽高的大小。
Mode 分三类:
EXACTLY:一般当layout_width或则layout_height为match_parent或则指定数值时,Mode为EXACTLY。
AT_MOST:一般当layout_width或则layout_height为wrap_content时。
UNSPECIFIED。
VIew中默认onMeasurea(),只支持EXACTLY。要想自定义控件支持wrap_content,必须在onMeasure中计算宽高。在onDraw()中绘画。
测量完成后,设置空间的宽高。
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    mheight = measuredHeight(heightMeasureSpec);    mwidth = measuredWidth(widthMeasureSpec);    setMeasuredDimension(mwidth, mheight);} private  int measuredWidth(int width){     int result = 0;     int specMode = MeasureSpec.getMode(width);     int specSize = MeasureSpec.getSize(width);     if(specMode == MeasureSpec.EXACTLY){         result = specSize;         Log.i("width", "specMode = MeasureSpec.EXACTLY"+ ",   specSize= "+ specSize+ ",  result = "+result);     }else{         result = 200;         if(specMode == MeasureSpec.AT_MOST){             result = result< specSize?result:specSize;             Log.i("width", "specMode = MeasureSpec.AT_MOST"+",   specSize= "+ specSize+ ",  result = "+result);         }         if(specMode == MeasureSpec.UNSPECIFIED){             Log.i("width", "specMode = MeasureSpec.AT_MOST");         }     }     return result; }
measuredHeight()和measuredWidth()类似。

2. 
一. 重写ViewGroup:
ViewGroup是容器。其中包括多个view。
onMeasure(int widthMeasureSpec, int heightMeasureSpec)中,测量子view和自己大小
onLayout()是抽象方法,自定义的ViewGroup必须实现该方法,在该方法中对子控件进行布局。
在onLayout()中调用子View的layout()方法。
1. 如下:我这只是简单的根据ViewGrouP大小划分子控件大小。
protected void onLayout(boolean changed, int l, int t, int r, int b) {    if (changed) {        int count = getChildCount();        int height = (b-t) / (count + 1);        Log.i("parent" , "l = " + l + ",t = " + t + ",r = " + r + ",b = " + b);        Log.i("child  height", String.valueOf(height));        for (int i = 0; i < count; i++) {            View child = getChildAt(i);            Log.i("child" + i, "l = " + l + ",t = " + i * height + ",r = " + r + ",b = " + (i + 1) * height);            child.layout(l, i * height, r, (i + 1) * height);//确定子控件的位置和大小。        }    }}

2. 也可以根据子控件的测量后的大小进行布局。这里只是线性竖直排列。
protected void onLayout(boolean changed, int l, int t, int r, int b) {    if (changed) {        int count = getChildCount();        int height = 0;        Log.i("viewgroup", ":  l = " + l + ",t = " + t + ",r = " + r + ",b = " + b);        // Log.i("child  height", String.valueOf(height));        for (int i = 0; i < count; i++) {            View child = getChildAt(i);            int cheight = child.getMeasuredHeight();  //获得子控件的高度            int cwidth = child.getMeasuredWidth();   //获得子控件的宽度            Log.i("viewgroup", "child: " + i + ",  l = " + l + ",t = " + (10 + height) + ",r = " + (l + cwidth) + ",b = " + (10 + height + cheight));            child.layout(l, 10 + height, l + cwidth, 10 + height + cheight);            height += cheight;        }    }}

0 0
原创粉丝点击