实现一个自定义View我们需要继承View或viewgroup,并且实现三个方法。
onMeasure(int widthMeasureSpec, int heightMeasureSpec) 测量的方法有三种测量模式,这里的值是获取的父view给的测量值
MeasureSpec.UNSPECIFIED 父容器对子View没有任何约束,子 View 可以按自身需要,任意大小。
MeasureSpec.AT_MOST 大小由view自身确定,不能超过父容器大小。wrap_content对应的就是它
MeasureSpec.EXACTLY 固定宽高,宽高都已经可以确定了,不能超过指定的大小。 match_parent和写死的大小对应它
通过 getMode getSize 获得当前的模式和size
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
注意在自定义view中获取子控件宽高都需要使用getMeasuredHeight|getMeasuredWidth
onLayout(int l, int t, int r, int b)
测量完后调用的方法,lt代表左上角的XY rb代表右下角的XY
**onDraw(Canvas canvas) **
知道了大小和怎么摆放现在就是画上去了
ViewGroup继承于View的子类 一个容器view继承它必须实现onLayout方法。调用顺序和View是一致的
下面是一段模仿LinearLayout的代码
public class TestGroup extends ViewGroup {
public TestGroup(Context context) {
super(context);
}
public TestGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TestGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.i("jinwei", "onMeasure");
measureChildren(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthMode == MeasureSpec.AT_MOST &&
heightMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(getWidthCount(), getHeightCount());
} else if (widthMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(getMeasuredWidth(), heightSize);
} else if (heightMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(widthSize, getHeightCount());
} else {
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.i("jinwei", "onLayout");
int count = getChildCount();
//记录当前的高度位置
int width = l;
for (int i = 0; i < count; i++) {
View childAt = getChildAt(i);
int measuredHeight = childAt.getMeasuredHeight();
int measuredWidth = childAt.getMeasuredWidth();
childAt.layout(0, width, measuredWidth, measuredHeight + width);
width += measuredHeight;
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i("jinwei", "onDraw");
}
private int getHeightCount() {
int count = getChildCount();
int maxHeight = 0;
for (int i = 0; i < count; i++) {
int height = getChildAt(i).getMeasuredHeight();
maxHeight += height;
}
return maxHeight;
}
private int getWidthCount() {
int count = getChildCount();
int maxWidth = 0;
for (int i = 0; i < count; i++) {
int width = getChildAt(i).getMeasuredWidth();
maxWidth += width;
}
return maxWidth;
}
}