mPrivateFlags
这是在view源码中很重要的一个变量,是一个int类型的32位值,开始只有这一个,后来不够用了,又产生了mPrivateFlags2,mPrivateFlags3。这个变量表示着非常多的意思。原因在于它表示了32个boolean类型的值。0表示false,1表示true。
下面继续我们的自定义测量:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width;
int height;
//MeasureSpec.AT_MOST;
//MeasureSpec.EXACTLY;
//MeasureSpec.UNSPECIFIED;
//int measureSpec = MeasureSpec.makeMeasureSpec(100, MeasureSpec.AT_MOST);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if(widthMode == MeasureSpec.EXACTLY){
width = widthSize;
} else {
if (orientation == 0){
width = drawable1.getIntrinsicWidth() + drawable2.getIntrinsicWidth();
} else {
width = Math.max(drawable1.getIntrinsicWidth(), drawable2.getIntrinsicWidth());
}
}
if(heightMode == MeasureSpec.EXACTLY){
height = heightSize;
} else {
if (orientation == 0){
height = Math.max(drawable1.getIntrinsicHeight(), drawable2.getIntrinsicHeight());
} else {
height = drawable1.getIntrinsicHeight() + drawable2.getIntrinsicHeight();
}
}
setMeasuredDimension(width, height);
}
作为一个正常的严谨的自定义测量,我们应该像上面的代码一样,经历以下几个步骤:
1。获取出父view传递过来的测量模式,判断是否为精确模式
2。如果不是精确模式,我们就测量自身大小。而如何进行测量就要靠具体自定义view的设计者去设计,没有通用的方式。
3。还要测量背景和最小宽高。之后和view的宽和高进行比较。都取相对大的值。
4。再加上左右padding的值。
5.这时我们已经取得了自定义view测量的最大值,还需要和父view给定的测量长度进行比对,取相对小的值。这样我们就取到了宽或高的最终值。
6。调用setMeasuredDimension(width, height)方法,将宽和高的最终值作为参数进行传递。这样测量工作就完成了。
那么父view(可以追溯到viewRoot)在调用measure()方法时,那两个参数是如何构建的呢?因为viewRoot知道屏幕有多大。手机在出厂的时候,在一个配置文件里面就有标明屏幕的宽和高的像素,viewRoot可以读取这个配置文件,获取到宽和高。打个比方,屏幕是1920乘以1080,那么viewRoot传递给decorView的两个参数是这样构建的:
int widthMeasureSpecDemo = MeasureSpec.makeMeasureSpec(1080, MeasureSpec.EXACTLY);
int heightMeasureSpecDemo = MeasureSpec.makeMeasureSpec(1920, MeasureSpec.EXACTLY);
之后就调用decorView的measure()方法向下传递。
测量的练习
需求:图片不能被拉变形,但是要适配屏幕。
分析:我们要知道图片的宽高比。按照比例来设定控件的大小。
方法1:通过layoutParams进行设置
方法2:通过调用测量进行测量
方法3:通过view.getViewTreeObserver().addOnGlobalLayoutListener();
这些些方法都是在view还不可见的情况下得到view的测量大小。但最好的办法是继承自imageview进行自定义控件。