关注
1
今天呢,我们一起来研究下怎么盖房子。(what!?) 同学们,房价这么贵,该自己学学怎么盖房子了。
大家是不是觉得楼主今天跑题啦,咱先别急,接着往下看。有时候我常想,很多技术的实现方式可能都来源于生活,但又高于生活。拿今天要讲的自定义View来说,其实我们在写自定义View的时候,需要去重写系统为我们设计好的一系列方法(如下所示):
onMeasure -> onLayout -> onDraw 这些方法。
细细一琢磨和盖房子的步骤还是蛮像的。那我们今天就先聊一聊第一步onMeasure。
2
盖房子的时候,我们先会确定一块地方,然后用工具量好建房子的地面范围,量好的这块地就是我们可以盖房子的范围。这个过程与我们在自定义View的onMeasure过程是类似的,都是确定一块我们接下来工作的范围。
测量的过程中,我们不单会测量整个房子的大小,我们要综合考虑房子里面的房间格局和大小。我们会测量卧室的大小,测量客厅的大小以及测量厨房的大小等等。
其实这个过程不总是那么顺利的,举个简单的例子:我期望有一个40平的卧室,40平的客厅,30平的厨房。
这么算下来总的需要110平吧,如果我们盖房子的用地能够满足,那我们可以愉快的按照这个期望值进行建造。可是有时候我们并没有那么大用地,我们只有80平的地,根本没法满足这些期望啊。
诶?那这房子还建不建了?建还是要建的,只不过不能完全满足期望而已嘛。我们可以有对卧室、客厅、厨房的美好生活向往嘛,但是美好生活向往的前提建立在伟大的特色社会主义的条件下的。社会主义教导我们“一切得从实际出发,实事求是!”。
建房子我们可以使用社会主义科学理论作为指导,那么在自定义View时,又怎么去指导我们何为实际?什么又是美好向往呢?诶?!对了,正如我们构建自定义View的时候,onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法中的两个参数就是我们科学理论指导嘛,是上级(父类)带给我们的科学指示,你所有对生活的美好向往都必须在这个条件下执行。这样才不会乱套,社会才能更和谐。你看,谷歌也深谙和谐与科学发展之道吧。
3
那么话又说回来了,这个限制到底是如何去限制呢?我们还拿建房子为例。
诶!?谷歌的工程师看到这一切,深深的吸了一口气,然后缓慢的吐出来,转身回到工位上,盯着想了很久的代码:
protected void onMeasure() {
// TODO 我该咋弄捏?
}
慢慢的嘴角露出一丝笑容,便顺手写下了:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
不错,是建房子给了他灵感,他将建房子限制的三个模式搬到了Android里面。在onMeasure中将上级(父类)的限制通过widthMeasureSpe和heightMeasureSpec对宽和高的限制传到子View中,子view通过:
final int specMode = MeasureSpec.getMode(measureSpec);
final int specSize = MeasureSpec.getSize(measureSpec);
上面的方式将限制条件读取出来,其中specMode就是上级的限制模式,specSize就是上级限制的尺寸。然后在我们的自定义View中计算自己的尺寸时,将自己期望的尺寸和父类的要求限制再传入resolveSizeAndState方法中(实际不是直接调用此方法,此处省略),然后在这个方法中,如果读取到限制的的模式是:
public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
final int specMode = MeasureSpec.getMode(measureSpec);
final int specSize = MeasureSpec.getSize(measureSpec);
final int result;
switch (specMode) {
case MeasureSpec.AT_MOST: // 限制上限模式
if (specSize < size) {
result = specSize | MEASURED_STATE_TOO_SMALL;
} else {
result = size;
}
break;
case MeasureSpec.EXACTLY: // 精确模式
result = specSize;
break;
case MeasureSpec.UNSPECIFIED:// 无限制模式
default:
result = size;
}
return result | (childMeasuredState & MEASURED_STATE_MASK);
}
做完这些测量以后呢,只需要调用setMeasureDimension将结果保存提交到国土局哦。
End
人民对美好生活的向往,与发展不平衡和不充分就这么愉快的解决了。父子兄弟之间的尺寸之争也被安排的妥妥的,整个社会一片和谐,人民安居乐业。
好了,onMeasure阶段就讲到这里了。下一节onLayout再见。拜拜~
动动小手,关注一下不迷路哦~