onMeasure
通过xml的layout_width/height指定自定义View的大小时,可以通过onMeasure指定View对于固定值、wrap_content、match_parent三种模式下的对应策略。
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int finalWidth, finalHeight;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
switch (widthMode) {
case MeasureSpec.EXACTLY:
finalWidth = widthSize;
break;
case MeasureSpec.AT_MOST: //解决wrap_content失效问题
finalWidth = 200;//可以通过自定义属性来设置
break;
default:
}
//...同样的方法用于finalHeight
setMeasuredDimension(finalWidth, finalHeight);
}
onDraw
在指定自定义View的大小后,就可以根据大小来绘制需要的图形,具体的方法是使用Paint、Canvas等类绘制。
自定义ViewGroup
测量方法onMeasure需要通过测量所能包含的子view的大小来指定,比如以下的一些方法:
//注意要与measureChild区分,measureChild是对单个view进行测量
measureChildren(widthMeasureSpec, heightMeasureSpec);
int childCount = getChildCount();
getMaxChildWidth();
getTotleHeight();
//...等等方法
测量大小之后,设置子View的摆放的规则,可以通过以下方法进行操作
int count = getChildCount();
View child = getChildAt(i);
int height = child.getMeasuredHeight();
//摆放子View,参数分别是子View矩形区域的左、上、右、下边
child.layout(l, t, r, b);
//...等等
组合型自定义View
通过组合一些系统已经拥有的控件来组合成一个可以通用的、逻辑上为一个复合组件的组件。某些情况下,需要写onMeasure,主要是防止wrap_content失效。不需要重写onLayout方法,因为子View的摆放已经通过xml文件指定了。这种做法的优点是制作流程简单,快速;缺点是定制性差,基本View的样子会固定。
本文深入解析自定义View与ViewGroup的核心方法onMeasure和onDraw,介绍如何通过onMeasure处理不同宽度模式,解决wrap_content失效问题。同时,探讨自定义ViewGroup的测量与布局策略,以及组合型自定义View的实现方式。
893

被折叠的 条评论
为什么被折叠?



