Android群英传学习笔记-自定义View
View的测量
MeasureSpec
android通过MeasureSpec来帮助我们测量View,MeasureSpec是一个32位的int值,其中高2位为测量模式,后30位为测量的大小,测量的模式分为以下三种。
- EXACTLY
精确值模式,当控件的layout_width或layout_height属性指定为具体值或match_parent时,系统使用EXACTLY模式。 - AT_MOST
最大值模式,当控件的layout_width或layout_height属性指定为wrap_content时,系统使用AT_MOST模式。 - UNSPECIFIED
这个属性比较奇怪,它不指定其大小测量模式,View想多大就多大,通常情况下在绘制自定义View时才会使用。
View类默认的onMeasure()只支持EXACTLY模式,所以在自定义view支持wrap_content属性,那么就必须重写onMeasure()方法来指定wrap_content时的大小。
相关代码
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}
private int measureWidth(int widthMeasureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(widthMeasureSpec);
int specWidth = MeasureSpec.getSize(widthMeasureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specWidth;
} else {
result = 200;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specWidth);
}
}
return result;
}
View的绘制
onDraw()方法中有一个参数,Canvas canvas对象,使用这个对象就可以进行绘图操作了。
ViewGroup的测量
当ViewGroup大小为wrap_content时,ViewGroup就需要对子View进行遍历,以便获得所有子view的大小,从而决定自己的大小。ViewGroup在测量时通过遍历所有ziview,从而调用View的Measure()方法来获得每个子view的测量结果。
当子View测量完毕后,需要将子View放到合适的位置,在自定义ViewGroup时,通常会去重写onLayout方法来控制子View显示位置。
ViewGroup的绘制
ViewGroup通常情况下不需要绘制,因为它本身就没有需要绘制的东西,如果不是指定了ViewGroup的背景颜色,连onDraw方法都不会被调用。但是,ViewGroup会使用dispathcDraw方法来绘制其他子View。
自定义View
在自定义View时,我们通常会重写onDraw方法来绘制View的显示内容,如果该View还需要使用wrap_content属性,那么还必须重写onMeasure方法,另外通过自定义attrs属性,还可以设置新的属性配置值。
在View中通常有以下一些比较重要的回调方法:
- onFinishInflate(): 从XML加载组件后回调。
- onSizeChanged(): 组件大小改变时回调。
- onMeasure(): 回调方法来进行测量。
- onLayout(): 回调该方法来确定显示位置。
- onTouchEvent(): 监听到触摸时间时回调。
对现有控件进行扩展