②View的measure方法会调用onMeasure方法,onMeasure会调用setMeasuredDimension方法设置View宽/高的测量值
2、View的onMeasure源码要点
//1. setMeasuredDimension方法设置View宽/高的测量值
setMeasuredDimension(
//2. 第一个参数是获得的测量宽/高(通过getDefaultSize获取)
getDefaultSize(getSuggestedMinimumWidth(), //3. 获取的建议最小的宽/高
widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(),
heightMeasureSpec));
}
1.setMeasuredDimension方法设置View宽/高的测量值(测量值通过getDefaultSize获取)
2.getDefaultSize用于获取View的测量宽/高
3、View的getDefaultSize源码要点(决定了View宽高的测量值)
public static int getDefaultSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
//2. UNSPECIFIED模式时,宽/高为第一个参数也就是getSuggestedMinimumWidth()获取的建议最小值
case MeasureSpec.UNSPECIFIED:
result = size;
break;
//3. AT_MOST(wrap_content)和EXACTLY(match_parent/具体值dp等)这两个模式下,View宽高的测量值为当前View的MeasureSpec(测量规格)中指定的尺寸specsize
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
4、View的getSuggestedMinimumWidth/Height()源码要点
protected int getSuggestedMinimumWidth() {
return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
}
1.如果View没有背景,View的最小宽度就为android:minWidth这个参数指定的值(mMinWidth),没有指定则默认为0
2.如果View有背景,会从mMinWidth和背景的最小宽度中取最大值。
3.背景的最小宽度(getMinimumWidth())本质就是Drawable的原始宽度(ShapeDrawable无原始宽度,BitmapDrawable有原始宽度——图片的尺寸)
5、View的wrap_content和match_parent效果一致的原因分析
①根据View的onMeasure方法中的getDefaultSize方法,我们可以发现在两种模式下,View的测量值等于该View的测量规格MeasureSpec中的尺寸。
②View的MeasureSpec本质是由自身的LayoutParams和父容器的MeasureSpec决定的。
③当View为wrap_content时,该View的模式为AT_MOST,且尺寸specSize为父容器的剩余空间大小。
④当View为match_parent时,该View的模式跟随父容器的模式(AT_MOST/EXACTLY), 且尺寸specSize为父容器的剩余空间大小。
⑤因此getDefaultSize中无论View是哪种模式,最终测量宽/高均等于尺寸specSize,因此两种属性效果是完全一样的(View的大小充满了父容器的剩余空间)
⑥除非给定View固定的宽/高,View的specSize才会等于该固定值。
6、自定义View需要重写onMeasure方法,并写明两种模式的处理方法
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
if(widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST){
//2. 均为wrap_content时, 将值设置为android:minWidth/Height属性指定的值
setMeasuredDimension(mWidth, mHeight);
}else if(widthSpecMode == MeasureSpec.AT_MOST){
//3. 哪个为wrap_content哪个就用android:minXXX属性给定的最小值
setMeasuredDimension(mWidth, heightSpecSize);
}else if(heightSpecMode == MeasureSpec.AT_MOST){
setMeasuredDimension(widthSpecSize, mHeight);
}
}
7、ViewGroup(抽象类)的measure流程
①ViewGroup没有onMeasure方法,只定义了measureChildren方法(onMeasure根据不同布局难以统一)
②measureChildren中遍历所有子元素并调用measureChild方法
③measureChild方法中会获取子View的MeasureSpec,然后调用子元素View的measure方法进行测量
想获取相关更多Android群653583088。本群提供免费的学习指导以及免费的解答不懂得问题都可以在本群提出来 之后还会有职业生涯规划以及面试指导进群修改群备注:开发年限-地区-经验方便解答问题
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
最后
考虑到文章的篇幅问题,我把这些问题和答案以及我多年面试所遇到的问题和一些面试资料做成了PDF文档,如果有需要的朋友可以私信我【面试】免费领取
sdn.net/topics/618156601)**
[外链图片转存中…(img-bA3V3rOE-1710505553633)]
[外链图片转存中…(img-pqZN1BfE-1710505553633)]
喜欢的朋友可以关注、转发、点赞 感谢!