自定义View
程序员文章站
2022-05-30 20:26:52
...
MeasureSpec哪里来的
ViewGroup.java getChildMeasureSpec()
//测量子view
protected void measureChild(View child, int parentWidthMeasureSpec,
int parentHeightMeasureSpec) {
//子view的宽高 match_parent wrap_content 或者具体数值
final LayoutParams lp = child.getLayoutParams();
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
mPaddingLeft + mPaddingRight, lp.width);
final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
mPaddingTop + mPaddingBottom, lp.height);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
//Spec父容器对子view的要求
//padding子view的padding
//childDimension 子view想要的尺寸
public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
int specMode = MeasureSpec.getMode(spec);//父类对子类的模式要求
int specSize = MeasureSpec.getSize(spec);//父类告诉子类的尺寸
int size = Math.max(0, specSize - padding);//如果padding的尺寸比父类给的尺寸还大就用0
int resultSize = 0;
int resultMode = 0;
switch (specMode) {
//父容器为精确模式 知道自己的具体尺寸
// Parent has imposed an exact size on us
case MeasureSpec.EXACTLY:
//子view设置了具体的值 入layout_width = "100dp"
// 则使用子类设置的值 测量模式使用精确
if (childDimension >= 0) {
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
}
//子view想和父容器一样大
//使用父容器的尺寸 测量模式为精确
else if (childDimension == LayoutParams.MATCH_PARENT) {
resultSize = size;
resultMode = MeasureSpec.EXACTLY;
}
//子view想用自己的尺寸 但是他的大小不能超过父容器大小 所以resultSize使用父容器大小
//子view的模式就是AT_MOST 即不能超过我给你的大小
else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size. It can't be
// bigger than us.
resultSize = size;//给他父容器尺寸,最大尺寸不能超过父类尺寸
resultMode = MeasureSpec.AT_MOST;
}
break;
//父容器 测量模式为最大模式的话,即父容器不知道自己的尺寸,但是大小不能超过size
case MeasureSpec.AT_MOST:
//子View知道自己的尺寸 使用子view的尺寸 精确模式
if (childDimension >= 0) {
// Child wants a specific size... so be it
resultSize = childDimension;
resultMode = MeasureSpec.EXACTLY;
}
//子viwe想和父容器一样大,使用父容器的尺寸 最大模式
else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size, but our size is not fixed.
// Constrain child to not be bigger than us.
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
}
//子view想使用自己的最小值
//让子view自己测量 但最大不能超过父容器size
else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size. It can't be
// bigger than us.
resultSize = size;
resultMode = MeasureSpec.AT_MOST;
}
break;
// Parent asked to see how big we want to be
//父容器未定义尺寸
case MeasureSpec.UNSPECIFIED:
if (childDimension >= 0) {
// Child wants a specific size... let him have it
resultSize = childDimension;//让子view自己决定
resultMode = MeasureSpec.EXACTLY;
}
//子类想和父容器一样大,但是父容器不知道知己的尺寸,所以子view设置为0
else if (childDimension == LayoutParams.MATCH_PARENT) {
// Child wants to be our size... find out how big it should
// be
resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
resultMode = MeasureSpec.UNSPECIFIED;
}
//child 希望尺寸由自己决定,一般这个时候,父容器 会给它一个 Size 作为最大值限制,
//但是 父容器 本身也需要计算,所以只能设置为0,并且没有给child最大值的设定
//将child的测量模式设置为 UNSPECIFIED
else if (childDimension == LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size.... find out how
// big it should be
resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
resultMode = MeasureSpec.UNSPECIFIED;
}
break;
}
//noinspection ResourceType
return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
}
上一篇: 简单的自定义View TimePanel
下一篇: 检测文件是否有bom头
推荐阅读
-
Android 入门第十讲02-广播(广播概述,使用方法(系统广播,自定义广播,两个activity之间的交互和传值),EventBus使用方法,数据传递,线程切换,Android的系统广播大全)
-
Android 对话框dialog使用注意点(android.view.WindowManager$BadTokenException)
-
详解PyCharm 自定义文件和代码模板实例
-
CodeIgniter怎么更改view文件夹路径?_PHP教程
-
Android实现带数字的圆形进度条(自定义进度条)
-
android自定义view制作圆形进度条效果
-
Android制作简单垂直上拉下滑View效果
-
Android编程实现Toast自定义布局简单示例
-
php自定义类fsocket模拟post或get请求的方法_PHP
-
Android自定义相机实现定时拍照功能