小编已经学习了大半年的android了,今天鼓起勇气写一些博客来分享一下自己的学习心得,也顺便巩固一下自己的知识,同时也想和大家相互讨论相互交流。
废话不多说,昨天找了一个自定义View的demo,代码不多功能也比较简单。然后看到有个onMeasure方法的时候,感觉有点奇怪还TM是继承来的,这是个什么东西?于是小编就复制粘贴直接google一下,这里小编想提醒各位广大猿们,找资料啥的最好使用google,不是我故意黑,恕我直言百度太垃圾。言归正传,然后就看了一下,下面为大家总结一下我的疑惑和找到的答案。
首先是这个方法是什么鬼,干啥用的?
这个好解释,看方法名就知道肯定和布局大小啥的有关,然后再看看两个参数onMeasure(int widthMeasureSpec, int heightMeasureSpec),用脚趾头想都明白前面的想法是对的,并且这个方法是在父布局要放置这个子View的时候调用,看看要给多少位置给你。
然后顺着代码看到个这个方法
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
width = getViewWidth(widthMeasureSpec);
height = getViewHeight(heightMeasureSpec);
Log.i("log", "onMeasure...");
setMeasuredDimension(width, height);
}
----------------------------
private int getViewWidth(int widthMeasureSpec) {
int result = 0;
int mode = MeasureSpec.getMode(widthMeasureSpec);
int size = MeasureSpec.getSize(widthMeasureSpec);
if (mode == MeasureSpec.EXACTLY) {
result = size;
} else {
result = width;
if (mode == MeasureSpec.AT_MOST) {
result = Math.min(result, size);
}
}
return result;
}
很明显得到宽和高嘛,跳到下面方法看到有个MeasureSpec,这个又是啥,继续找答案。
一个MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求。一个MeasureSpec由大小和模式组成。它有三种模式:UNSPECIFIED(未指定),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;AT_MOST(至多),子元素至多达到指定大小的值。
它常用的三个函数:
1.static int getMode(int measureSpec):根据提供的测量值(格式)提取模式(上述三个模式之一)
2.static int getSize(int measureSpec):根据提供的测量值(格式)提取大小值(这个大小也就是我们通常所说的大小)
3.static int makeMeasureSpec(int size,int mode):根据提供的大小值和模式创建一个测量值(格式)。
看到这里似乎明白了点什么,也就是拿mode来判断一下他要的size取什么合适。
至于mode对应的常量是啥意思,这里再看一下别人怎么说的
match_parent—>EXACTLY。怎么理解呢?match_parent就是要利用父View给我们提供的所有剩余空间,而父View剩余空间是确定的,也就是这个测量模式的整数里面存放的尺寸。
wrap_content—>AT_MOST。怎么理解:就是我们想要将大小设置为包裹我们的view内容,那么尺寸大小就是父View给我们作为参考的尺寸,只要不超过这个尺寸就可以啦,具体尺寸就根据我们的需求去设定。
固定尺寸(如100dp)—>EXACTLY。用户自己指定了尺寸大小,我们就不用再去干涉了,当然是以指定的大小为主啦。
Ok,下面就走到setMeasuredDimension(width, height);这个方法就将值设置到了控件中。over!
这里有个小细节还要说一下,细心的朋友可能已经看到了我在onMeasure方法中打印了一个log。干啥用的捏?
因为在我跑这个demo的时候发现这个onMeasure执行不止一遍。
这就尴尬啦,什么鬼,好不容易看完了这几个蛋疼的方法,还TM搞这么一出。
小编本着一探到底的精神,继续找原因。一搜就恍然大悟,原来这个onMeasure是父视图在子视图上调用的。首先父视图将他的每个子视图都测量一次然后告诉子视图这个size合适不?如果子视图说不行不合适,那么父视图就会设置第二次测量规则。
好啦,以上就是小编自己学习总结的onMeasure,也不知道准不准确,如果有什么不对的地方希望大家指出来,大家共同讨论。