對View的onMeasure方法理解

      最近一直想作一個本身定義組建可一直苦於OnMeasure()不知道怎麼用,剛纔終於有時間來整理下個人東西了。
      咱們知道View在屏幕上顯示出來要先通過measure和layout. 在調用onMeasure(int widthSpec, int heightSpec)方法時,要涉及到MeasureSpec的使用,MeasureSpec有3種模式分別是 UNSPECIFIED, EXACTLY和AT_MOST , 那麼這些模式和咱們平時設置的layout參數fill_parent, wrap_content有什麼關係呢。 通過代碼測試就知道,當咱們設置width或height爲fill_parent時,容器在佈局時調用子 view的measure方法傳入的模式是EXACTLY,由於子view會佔據剩餘容器的空間,因此它大小是肯定的。而當設置爲 wrap_content時,容器傳進去的是AT_MOST, 表示子view的大小最可能是多少,這樣子view會根據這個上限來設置本身的尺寸 。當子view的大小設置爲精確值時,容器傳入的是EXACTLY, 而MeasureSpec的UNSPECIFIED模式目前尚未發如今什麼狀況下使用。 
   View的onMeasure方法默認行爲是當模式爲UNSPECIFIED時,設置尺寸爲mMinWidth(一般爲0)或者背景drawable的最小尺寸,當模式爲EXACTLY或者AT_MOST時,尺寸設置爲傳入的MeasureSpec的大小。 

   有個觀念須要糾正的是,fill_parent應該是子view會佔據剩下容器的空間,而不會覆蓋前面已佈局好的其餘view空間,固然後面佈局子 view就沒有空間給分配了,因此fill_parent屬性對佈局順序很重要。之前所想的是把全部容器的空間都佔滿了,難怪google在2.2版本里 把fill_parent的名字改成match_parent. java


onMeasure方法在控件的父元素正要放置它的子控件時調用.它會問一個問題,「你想要用多大地方啊?」,而後傳入兩個參數——widthMeasureSpec和heightMeasureSpec.

  它們指明控件可得到的空間以及關於這個空間描述的元數據.
  比返回一個結果要好的方法是你傳遞View的高度和寬度到setMeasuredDimension方法裏.

  接下來的代碼片斷給出瞭如何重寫onMeasure.注意,調用的本地空方法是來計算高度和寬度的.它們會譯解widthHeightSpec和heightMeasureSpec值,並計算出合適的高度和寬度值.

java代碼: 框架

  1. @Override
  2. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

  3. int measuredHeight = measureHeight(heightMeasureSpec);
  4. int measuredWidth = measureWidth(widthMeasureSpec);
  5. setMeasuredDimension(measuredHeight, measuredWidth);
  6. }

  7. private int measureHeight(int measureSpec) {


  8. // Return measured widget height.
  9. }

  10. private int measureWidth(int measureSpec) {

  11. // Return measured widget width.
  12. }
複製代碼


       邊界參數——widthMeasureSpec和heightMeasureSpec ,效率的緣由以整數的方式傳入。 ide

      

     MeasureSpec封裝了父佈局傳遞給子佈局的佈局要求,每一個MeasureSpec表明了一組寬度和高度的要求。一個MeasureSpec由大小和模式組成。 函數

    它有三種模式: 佈局

                    UNSPECIFIED(未指定),     父元素不對自元素施加任何束縛,子元素能夠獲得任意想要的大小; 測試

                    EXACTLY(徹底),父元素決定自元素的確切大小,子元素將被限定在給定的邊界裏而忽略它自己大小; this

                    AT_MOST(至多),子元素至多達到指定大小的值。 google

   它經常使用的三個函數: idea

    1.static int getMode(int measureSpec):根據提供的測量值(格式)提取模式(上述三個模式之一) spa

  2.static int getSize(int measureSpec):根據提供的測量值(格式)提取大小值(這個大小也就是咱們一般所說的大小)

  3.static int makeMeasureSpec(int size,int mode):根據提供的大小值和模式建立一個測量值(格式)

     這個類的使用呢,一般在view組件的onMeasure方法裏面調用但也有少數例外

 

       在它們使用以前,首先要作的是使用MeasureSpec類的靜態方法getMode和getSize來譯解,以下面的片斷所示:

java代碼:

  1. int specMode = MeasureSpec.getMode(measureSpec);
  2. int specSize = MeasureSpec.getSize(measureSpec);
複製代碼


       依據specMode的值,若是是AT_MOST,specSize 表明的是最大可得到的空間;若是是EXACTLY,specSize 表明的是精確的尺寸;若是是UNSPECIFIED,對於控件尺寸來講,沒有任何參考意義。
  當以EXACT方式標記測量尺寸,父元素會堅持在一個指定的精確尺寸區域放置View。在父元素問子元素要多大空間時,AT_MOST指示者會說給我最大的範圍。在不少狀況下,你獲得的值都是相同的。
  在兩種狀況下,你必須絕對的處理這些限制。在一些狀況下,它可能會返回超出這些限制的尺寸,在這種狀況下,你可讓父元素選擇如何對待超出的View,使用裁剪仍是滾動等技術。

  接下來的框架代碼給出了處理View測量的典型實現:

java代碼:

  1. @Override

  2. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

  3. int measuredHeight = measureHeight(heightMeasureSpec);

  4. int measuredWidth = measureWidth(widthMeasureSpec);

  5. setMeasuredDimension(measuredHeight, measuredWidth);

  6. }

  7. private int measureHeight(int measureSpec) {

  8. int specMode = MeasureSpec.getMode(measureSpec);
  9. int specSize = MeasureSpec.getSize(measureSpec);

  10. // Default size if no limits are specified.

  11. int result = 500;
  12. if (specMode == MeasureSpec.AT_MOST){

  13. // Calculate the ideal size of your
  14. // control within this maximum size.
  15. // If your control fills the available
  16. // space return the outer bound.

  17. result = specSize;

  18. else if (specMode == MeasureSpec.EXACTLY){

  19. // If your control can fit within these bounds return that value.
  20. result = specSize;
  21. }

  22. return result;
  23. }

  24. private int measureWidth(int measureSpec) {
  25. int specMode = MeasureSpec.getMode(measureSpec);
  26. int specSize = MeasureSpec.getSize(measureSpec);

  27. // Default size if no limits are specified.
  28. int result = 500;
  29. if (specMode == MeasureSpec.AT_MOST){
  30. // Calculate the ideal size of your control
  31. // within this maximum size.
  32. // If your control fills the available space
  33. // return the outer bound.
  34. result = specSize;


  35. else if (specMode == MeasureSpec.EXACTLY){
  36. // If your control can fit within these bounds return that value.

  37. result = specSize;
  38. }

  39. return result;
  40. }
相關文章
相關標籤/搜索