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进行自定义控件。

results matching ""

    No results matching ""