在自定义控件中,可以重新定义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; } } }