view 的測量過程源碼分析及應用

講解過程:

1.測量方式分析,比對不同測量模式的差異,包括應用分析。

2.分析源碼中view的具體繪製流程

3.測量的實際應用

 

1.測量方式分析,對不同測量模式的差異,包括應用分析。

說起測量我們最直觀和常見的是onMeasure方法。

public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)

這裏會有兩個參數,分別對應的是view的寬度和高度的測量規格。該參數是一個32位的int類型數據,

該參數包含了兩條信息,分別是測量模式和測量值(寬度或者高度值)

  /**
         * 獲取測量模式
         */
        int specMode = MeasureSpec.getMode(measureSpec);
        /**
         * 獲取view的測量值
         */
        int specSize = MeasureSpec.getSize(measureSpec);

32位的高兩位表示測量模式,低30位表示測量值。

測量模式分爲三種模式。

1.EXACTLY match_parent 或者確定值模式,默認是這種測量模式(如果你使用的是view的子類,那麼測量模式會有變化)

2.AT_MOST  wrap_content 需要重寫onMeasure方法    最大值模式

3.UNSPECIFIED  自定義控件有用

剛纔說默認的測量模式是確定值模式,現在就來看下。

自定義TextView   MyTextView類

 

public class MyTextView extends android.support.v7.widget.AppCompatTextView {
    Context context;
    public MyTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.context=context;
    }
}

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.macbook.demoproject.measure.MyTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="ddddddddddddddd"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="6dp"
        android:paddingLeft="4dp"
        android:paddingRight="3dp"
        android:textColor="@color/colorAccent"
        android:textSize="30sp"
        android:background="#00ff00" />
</LinearLayout>

顯示效果

效果圖
標題

這是因爲我們繼承的是TextView ,它本身已經實現了onMeasure 方法,所以不會顯示 全屏,現在我們改下,將TextView 改爲View Group

public class MyGroupMeasureVeiw extends ViewGroup {
    public MyGroupMeasureVeiw(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

    }
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
<com.example.macbook.demoproject.measure.MyGroupMeasureVeiw
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/holo_blue_bright">

</com.example.macbook.demoproject.measure.MyGroupMeasureVeiw>
</LinearLayout>

viewGroup

   所以,如果繼承了viewGroup 不重寫onmeasure 默認是會全屏顯示的,也就是精確值模式。那麼上邊我們看到,如果繼承了TextView 同樣使用了wrap_content 顯示的是最大值效果,那是因爲TextView 重寫onMeasure方法,重新計算了view的測量模式。

下面我們就來新建一個自定義的類繼承自ViewGroup,實現控件填充自動收縮大小。

package com.example.macbook.demoproject.measure;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by LCT
 * Time:2019/3/13 11:26.
 * Annotation:
 */
public class MyGroupMeasureVeiw extends ViewGroup {
    private static final String TAG = "MyGroupMeasureVeiw";
    Context context;
    int widthL;
    /**
     * 父類最大寬度
     */
    int maxViewGroupWidth = 0;

    public MyGroupMeasureVeiw(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        int d = (int) context.getResources().getDisplayMetrics().xdpi;
        widthL = context.getResources().getDisplayMetrics().widthPixels;
        int dsdd = context.getResources().getDisplayMetrics().heightPixels;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         measureChildren(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int childCount = getChildCount();
        if (childCount == 0) {//如果沒有子View,當前ViewGroup沒有存在的意義,不用佔用空間
            setMeasuredDimension(0, 0);
        } else {
            int height = getTotleHeight();
            int width = maxViewGroupWidth != 0 ? maxViewGroupWidth : getMaxChildWidth();
            //如果寬高都是包裹內容最大值模式
            if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
                //我們將高度設置爲所有子View的高度相加,寬度設爲子View中最大的寬度
                setMeasuredDimension(width, height);
            } else if (heightMode == MeasureSpec.AT_MOST) {
                //如果只有高度是包裹內容最大值模式
                //寬度設置爲ViewGroup自己的測量寬度,高度設置爲所有子View的高度總和
                setMeasuredDimension(widthSize, height);
            } else if (widthMode == MeasureSpec.AT_MOST) {
                //如果只有寬度是包裹內容
                //寬度設置爲子View中寬度最大的值,高度設置爲ViewGroup自己的測量值
                setMeasuredDimension(width, heightSize);
            }
        }
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        //記錄當前的高度位置
        int childCount = getChildCount();
        /**
         * 保存一行中高度最大的一個view的高度包括margin值
         */
        int maxHeight = 0;
        /**
         * y軸方向每次需要累加的view的高度,用於計算Y值得大小
         */
        int maxYHeight = 0;
        /**
         * view x軸方向最大寬度用於判斷view是否需要換行
         */
        int maxWidth = 0;
        /**
         * 左邊距離
         */
        int x = 0;
        /**
         * 右邊距離
         */
        int y = 0;
        /**
         * 右側距離
         */
        int xw = 0;
        /**
         *
         */
        int yh = 0;
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            final MarginLayoutParams lp = (MarginLayoutParams) childView.getLayoutParams();
            /**
             * 獲取當前view的高度
             */
            int height = childView.getMeasuredHeight();
            int heightds = childView.getHeight();
            /**
             * 獲取當前view的寬度
             */
            int width = childView.getMeasuredWidth();
            /**
             * 獲取當前view的寬度包含margin值因爲在實際的控件擺放中是需要將margin值空出來的
             */
            int viewWidth = childView.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            x += lp.leftMargin;
            y = lp.topMargin + maxYHeight;
            xw = x + width;
            yh = y + height;
            if (maxWidth <= widthL && (maxWidth + viewWidth) >= widthL) { //view在本行放滿了累加本行最大高度
                /**
                 * 換行只和y軸方向座標有關x方向恢復默認
                 */
                x = lp.leftMargin;
                xw = x + width;

                maxWidth = viewWidth;
                maxYHeight += maxHeight;
                y = maxYHeight + lp.topMargin;
                yh = y + height;
                Log.d(TAG, "getTotleHeight: maxHeight:" + y);
            } else {
                maxWidth += viewWidth;
                //獲取一行中高度最大的view的高度
                int hHeight = height + lp.topMargin + lp.bottomMargin;
                if (maxHeight < hHeight) {
                    maxHeight = hHeight;
                }
                Log.d(TAG, "getTotleHeight: maxWidth:" + maxWidth);
            }
            Log.d(TAG, "getTotleHeight onLayout: l" + x + "t: " + y + "r: " + xw + "b: " + yh);
            childView.layout(x, y, xw, yh);
            /**
             *view擺放成功後將 marginLeft + width + marginRight 得到X 保存一個完整的view所佔的寬度
             */
            x = xw + lp.rightMargin;
        }
    }

    /***
     * 獲取子View中寬度最大的值
     */
    private int getMaxChildWidth() {
        int childCount = getChildCount();
        int maxWidth = 0;
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            final MarginLayoutParams lp = (MarginLayoutParams) childView.getLayoutParams();
            /**
             * 獲取當前view的寬度
             */
            int width = childView.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            //view 寬度累計大於屏幕寬度,將寬度設置爲設備寬度
            if (maxWidth <= widthL && (maxWidth + width) >= widthL) {
                maxWidth = widthL;
                Log.d(TAG, "getTotleHeight: maxHeight:" + maxWidth);
                return maxWidth;
            } else {
                maxWidth += width;
                Log.d(TAG, "getTotleHeight: maxWidth:" + maxWidth);
            }
        }
        return maxWidth;
    }

    /***
     * 將所有子View的高度相加
     **/
    private int getTotleHeight() {
        int childCount = getChildCount();
        int maxHeight = 0;
        int maxYHeight = 0;
        int maxWidth = 0;
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            final MarginLayoutParams lp = (MarginLayoutParams) childView.getLayoutParams();

            /**
             * 獲取當前view的高度
             */
            int height = childView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
            /**
             * 獲取當前view的寬度
             */
            int width = childView.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
            //view在本行放滿了累加本行最大高度,用於計算viewgroup高度
            if (maxWidth <= widthL && (maxWidth + width) >= widthL) {
                maxViewGroupWidth = widthL;
                maxYHeight += maxHeight;
                maxHeight = 0;
                maxWidth = 0;
                Log.d(TAG, "getTotleHeight: maxHeight:" + maxYHeight);
            } else {
                maxWidth += width;
                //獲取一行中高度最大的view的高度
                if (maxHeight < height) {
                    maxHeight = height;
                }
                maxViewGroupWidth=maxWidth;
                Log.d(TAG, "getTotleHeight: maxWidth:" + maxHeight);
            }
        }
        if (maxViewGroupWidth!=widthL) {
            maxYHeight=maxHeight;
        }
        return maxYHeight;
    }
}

使用的xml   measure_group_layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_blue_dark">

    <com.example.macbook.demoproject.measure.MyGroupMeasureVeiw
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@android:color/holo_blue_bright"
        android:padding="10dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:background="@android:color/white"
            android:gravity="center"
            android:padding="20dp"
            android:text="打ffffffffffffff快點1"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="15sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:background="@android:color/white"
            android:padding="20dp"
            android:text="打fffffffffdsdfvbfd快點2"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="15sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:background="@android:color/white"
            android:padding="20dp"
            android:text="打快點3"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="15sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:background="@android:color/white"
            android:padding="20dp"
            android:text="打快dfdsdaaaaaaaaaaaadad點4"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="15sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:background="@android:color/white"
            android:padding="20dp"
            android:text="打快點5"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="15sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:background="@android:color/white"
            android:padding="20dp"
            android:text="打快dsddadf點6"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="15sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:background="@android:color/white"
            android:padding="20dp"
            android:text="打快dsddadf點7"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="15sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:padding="20dp"
            android:text="打快dsddadf點8"
            android:background="@android:color/white"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="15sp" />




        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:background="@android:color/white"
            android:gravity="center"
            android:padding="20dp"
            android:text="打ffffffffffffff快點1"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="15sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:background="@android:color/white"
            android:padding="20dp"
            android:text="打fffffffffdsdfvbfd快點2"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="15sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:background="@android:color/white"
            android:padding="20dp"
            android:text="打快點3"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="15sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:background="@android:color/white"
            android:padding="20dp"
            android:text="打快dfdsdaaaaaaaaaaaadad點4"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="15sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:background="@android:color/white"
            android:padding="20dp"
            android:text="打快點5"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="15sp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:background="@android:color/white"
            android:padding="20dp"
            android:text="打快dsddadf點6"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="15sp" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:background="@android:color/white"
            android:gravity="center"
            android:padding="20dp"
            android:text="打ffffffffffffff快點1"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="15sp" />


    </com.example.macbook.demoproject.measure.MyGroupMeasureVeiw>

</LinearLayout>

 

2.分析源碼中view的具體繪製流程

現在我們直接看自定義類MyGroupMeasureVeiw,它繼承自ViewGroup ,默認重寫onLayout方法,現在我們直接看onMeasure方法。

measureChildren(widthMeasureSpec, heightMeasureSpec);用於測量子view測量模式,只有經過測量後才能獲取到子view 的相關信息,比如寬度,高度等。
protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
        final int size = mChildrenCount;
        final View[] children = mChildren;
        for (int i = 0; i < size; ++i) {
            final View child = children[i];
            if ((child.mViewFlags & VISIBILITY_MASK) != GONE) {
                measureChild(child, widthMeasureSpec, heightMeasureSpec);
            }
        }
    }

這裏傳入的兩個參數分別是高度和寬度的測量模式,,然後將父類的測量模式傳給子類進行操作,調用了measureChild方法,這裏是獲取了所有子類,一個一個測量。

protected void measureChild(View child, int parentWidthMeasureSpec,
            int parentHeightMeasureSpec) {
        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);
    }

 

這裏分別調用了getChildMeasureSpec 根據父類的測量模式來生成子類的測量規則,具體分析下getChildMeasureSpec 方法,針對寬度測量規則看下。

這裏三個參數分別是:父類的寬度測量規則,父類的左右兩側的padding值,以及子類的寬度,這裏我直接在源碼中備註了

public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
        /**
         * 獲取測量模式
         */
        int specMode = MeasureSpec.getMode(spec);
        /**
         * 獲取控件的寬度
         */
        int specSize = MeasureSpec.getSize(spec);
        /**
         * 獲取子類可用的最大寬度
         * 這裏減去父類的左右padding剩下的纔是子類可用的
         */
        int size = Math.max(0, specSize - padding);

        int resultSize = 0;
        int resultMode = 0;
        /**
         * 根據父類的測量模式設置子類的測量模式
         */
        switch (specMode) {
            // Parent has imposed an exact size on us
            /**
             * 父類是精確值模式,childDimension大於0或者是MATCH_PARENT 則子類的模式是精確值模式,
             * 如果子類是WRAP_CONTENT
             * 那麼子類的測量模式爲最大值模式AT_MOST,既子類的寬度等於(padding忽略)父類的寬度
             */
            case MeasureSpec.EXACTLY:
                if (childDimension >= 0) {
                    resultSize = childDimension;
                    resultMode = MeasureSpec.EXACTLY;
                } else if (childDimension == LayoutParams.MATCH_PARENT) {
                    // Child wants to be our size. So be it.
                    resultSize = size;
                    resultMode = MeasureSpec.EXACTLY;
                } 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 has imposed a maximum size on us
            /**
             * 父類是最大值模式:
             * 1.如果子類childDimension >= 0 那麼子類就是精確值模式
             * 2.childDimension == LayoutParams.MATCH_PARENT 子類是精確值模式MATCH_PARENT,它的寬度大小和父類的寬度一樣
             * 父類是最大值模式,所以子類的模式也是最大值模式AT_MOST
             * 3.childDimension == LayoutParams.WRAP_CONTENT 父類都是最大值模式,子類的寬度是WRAP_CONTENT最大值模式,
             * 所以子類也是最大值模式AT_MOST 寬度和父類寬度一樣
             *
             */
            case MeasureSpec.AT_MOST:
                if (childDimension >= 0) {
                    // Child wants a specific size... so be it
                    resultSize = childDimension;
                    resultMode = MeasureSpec.EXACTLY;
                } 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;
                } 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
            /**
             * 這個稍微難理解,多用於自定模式
             * 1.如果子類是具體值那麼,設置它爲精確值模式
             * 2.如果子類是MATCH_PARENT 或者  WRAP_CONTENT 模式,那麼子類的大小有可能和父類一樣大,
             * 設置子類爲自定義模式UNSPECIFIED
             * View.sUseZeroUnspecifiedMeasureSpec 單獨看下這個,字面意思是說,用戶沒有指定它的的測量模式
             * 它的默認值是0,sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
             * 當targetSdkVersion小於23時爲true resultSize爲0,否則resultSize爲父類的大小
             */
            case MeasureSpec.UNSPECIFIED:
                if (childDimension >= 0) {
                    // Child wants a specific size... let him have it
                    resultSize = childDimension;
                    resultMode = MeasureSpec.EXACTLY;
                } 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;
                } 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);
    }

3.測量的實際應用

 

現在知道子類是如何根據父類的測量規則生成自己的測量規則,繼續回到MyGroupMeasureVeiw 類的onMeasure 方法中,

measureChildren已經看完了,他就是將所有子類生成了測量規格。看完了對子view的測量,我們結合代碼需求來設置父veiw的尺寸

假設父類寬高都是最大值模式。要求是子類一次從左到右根據內容大小自適應顯示寬高,當一行放不下時換到另一行顯示,然後計算出父類view的寬高。

getTotleHeight 返回 將所有子View擺放的每行的高度相加
if (widthMode == MeasureSpec.AT_MOST && heightMode == MeasureSpec.AT_MOST) {
    //我們將高度設置爲所有子View的高度相加,寬度設爲子View中最大的寬度
    setMeasuredDimension(width, height);
} 
int height = getTotleHeight();
int width = maxViewGroupWidth != 0 ? maxViewGroupWidth : getMaxChildWidth();

這裏獲取到了高度和寬度,也就是說我們根據子類的顯示方式去動態指定了一個父類的寬高,建議將onlayout 方法內容註釋掉來理解。

關於 getTotleHeight() 和 getMaxChildWidth()我們大概看先上面的具體哪內容,備註寫的比較完善,主要就是如何獲根據子類,的位置及寬高,去計算自適應父類的寬高尺寸。

setMeasuredDimension方法用於設置view的寬高,這樣viewGroup及基本的view的測量及簡單應用就完成了。其實就是通過對子類的測量計算,得到一個自己想要的父類的大小。

這樣就完了麼,貌似少了點啥啊,還有常用的兩個方法大概講下吧。

getDefaultSize 和 getSuggestedMinimumWidth方法沒講。
   public static int getDefaultSize(int size, int measureSpec) {
        int result = size;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        switch (specMode) {
        case MeasureSpec.UNSPECIFIED:
            result = size;
            break;
        case MeasureSpec.AT_MOST:
        case MeasureSpec.EXACTLY:
            result = specSize;
            break;
        }
        return result;
    }

這個方法就是獲取默認的view的大小的,size可以是我們制定的一個數值也可以獲取系統獲取到的值,例如可以這麼用

setMeasuredDimension( getDefaultSize(30,MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec),MeasureSpec.UNSPECIFIED)),getDefaultSize(200,MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),MeasureSpec.UNSPECIFIED)));

這裏寬度的size設置爲30 ,測量模式我給他設置爲UNSPECIFIED 所以得到的getDefaultSize的返回值就是30 那麼同理,高度是200,這個在自定義的控件中非常重要。

接下來看下getSuggestedMinimumWidth()這裏getSuggestedMinimumHeight()類似,只看一個就好了

protected int getSuggestedMinimumWidth() {
        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
    }

就是獲取view 所佔的最小值,寬度或者高度。

好了,關於view的測量我們就將到這裏,下一篇我們將接着這篇來看下view 是如何擺放的onLayout方法。

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章