學習日誌-onMeasure等問題

一、

注意:從Android2.2開始,爲了更好的使用,fill_parent被改爲match_parent。因爲當我們把一個子部件設置爲fill_parent之後,該部件不是佔有同等級部件剩餘的空間,而是和同等級部件重疊在一起。相反,使用match_parent則不會出現重疊的現象。


二、

佈局參數

XML佈局屬性layout_something被定義爲佈局參數,它們被View和ViewGroup所恰當的保留。每ViewGroup的類實現一個嵌套類擴展ViewGroup.LayoutParams的。這個子類包含的屬性類型定義爲每個子視圖的大小和位置,作適當的視圖組。正如你可以看到下圖中,父視圖組定義爲每個子視圖(包括子視圖組)的佈局參數。

每個佈局的參數其實是父佈局的類型,因爲它依賴於父佈局而存在的:



圖片介紹:可視化的視圖層次的每個視圖的佈局參數 請注意,每一個的LayoutParams子類有它自己的語法設定值。每個子元素必須定義相對它父類合適的LayoutParams,儘管它也可以爲自己的子類定義不同的LayoutParams。 所有的視圖組包括一個寬度和高度(layout_width和layout_height),每個視圖需要定義它們。許多的LayoutParams也包括可選的邊距和邊框。您可以指定寬度和高度精確的值。大部分您將使用這些常量類設置寬度或高度:wrap_content其內容所需的尺寸大小本身。fill_parent(API等級8改名爲match_parent,與它的父視圖組一樣大。在一般情況下,不建議指定一個佈局使用絕對單位,如像素的寬度和高度。相反,推薦採用相對測量,如獨立的像素密度單位(DP),wrap_content,或fill_parent,因爲它有助於確保您的應用程序將在各種設備的屏幕尺寸顯示正確。

佈局位置

一個View的幾何形狀是一個矩形。每一個view的位置都可以用一個座標和兩個尺寸所表示,一個座標指的是相對最左邊和相對最頂部的兩個點,兩個尺寸是指它的高度和寬度。位置和尺寸的單位都是像素。可以調用視圖的方法來獲得它的位置, getLeft() 返回左側的或者X的座標,getTop()返回頂部或者Y的座標。這兩個方法返回的位置都是相對於它的父容器的位置。例如當getLeft()返回20的時候,說明這個view相對於它的父容器的最左邊邊緣20像素的位置。此外還提供了getRight(),getBottom()方法來滿足一些其他的計算,調用getRight()時類似與getLeft()的計算。


三、對於所有的View默認的權重是0,如果你只設置了一個View的權重大於0,那麼這個View將佔據除去別的View本身佔據的空間的的所有剩餘空間。因此這裏設置EditText的權重爲1保持button沒有權重值的狀態,使EditText能夠佔據除了按鈕之外的所有空間。


四、最重要的一個問題:

getWidth(): View在設定好佈局後整個View的寬度。

 getMeasuredWidth(): 對View上的內容進行測量後得到的View內容佔據的寬度,前提是你必須在父佈局的onLayout()方法或者此View的onDraw()方法裡調 用measure(0,0);(measure 參數的值你可以自己定義),否則你得到的結果和getWidth()得到的結果一樣。


在View裏面你可以重寫onDraw

 public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
        if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
                widthMeasureSpec != mOldWidthMeasureSpec ||
                heightMeasureSpec != mOldHeightMeasureSpec) {

            // first clears the measured dimension flag
            mPrivateFlags &= ~MEASURED_DIMENSION_SET;

            if (ViewDebug.TRACE_HIERARCHY) {
                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
            }

            // measure ourselves, this should set the measured dimension flag back
            onMeasure(widthMeasureSpec, heightMeasureSpec);

            // flag not set, setMeasuredDimension() was not invoked, we raise
            // an exception to warn the developer
            if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
                throw new IllegalStateException("onMeasure() did not set the"
                        + " measured dimension by calling"
                        + " setMeasuredDimension()");
            }

            mPrivateFlags |= LAYOUT_REQUIRED;
        }

        mOldWidthMeasureSpec = widthMeasureSpec;
        mOldHeightMeasureSpec = heightMeasureSpec;
    }

在這裏面它進行了計算自己有多大,它的兩個參數值就是XML佈局傳過去的,然後它把onMeasure這個方法暴露出去,你View可以通過調用這個方法來獲取它的數據和修改它的數據,

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
    }

如果父View調用了它的這個方法,可以修改它寬高,然後在最終渲染的時間,表現出來,而getWidth只是獲取它顯示到某個界面的實際寬度。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章