Android自定義ViewGroup View的大小和座標控制

yangxi_001發表於2013-11-22
[java] view plaincopy
  1. 除非你總是需要一個100×100畫素的控制元件,否則,你必須要重寫onMeasure。  
  2.   
  3. onMeasure方法在控制元件的父元素正要放置它的子控制元件時呼叫。它會問一個問題,“你想要用多大地方啊?”,然後傳入兩個引數——widthMeasureSpec和heightMeasureSpec。  
  4. 它們指明控制元件可獲得的空間以及關於這個空間描述的後設資料。  
  5.   
  6.  比返回一個結果要好的方法是你傳遞View的高度和寬度到setMeasuredDimension方法裡。  
  7. 接下來的程式碼片段給出瞭如何重寫onMeasure。注意,呼叫的本地空方法是來計算高度和寬度的。它們會譯解widthHeightSpec和heightMeasureSpec值,並計算出合適的高度和寬度值。  
  8.   
  9.    
  10.   
  11. @Override  
  12.   
  13. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  14.   
  15. int measuredHeight = measureHeight(heightMeasureSpec);  
  16.   
  17. int measuredWidth = measureWidth(widthMeasureSpec);  
  18.   
  19. setMeasuredDimension(measuredHeight, measuredWidth);  
  20.   
  21. }  
  22.   
  23.    
  24.   
  25. private int measureHeight(int measureSpec) {  
  26.   
  27. // Return measured widget height.  
  28.   
  29. }  
  30.   
  31.    
  32.   
  33. private int measureWidth(int measureSpec) {  
  34.   
  35. // Return measured widget width.  
  36.   
  37. }  
  38.   
  39.    
  40.   
  41. 邊界引數——widthMeasureSpec和heightMeasureSpec ,效率的原因以整數的方式傳入。在它們使用之前,首先要做的是使用MeasureSpec類的靜態方法getMode和getSize來譯解,如下面的片段所示:  
  42.   
  43.    
  44.   
  45. int specMode = MeasureSpec.getMode(measureSpec);  
  46.   
  47. int specSize = MeasureSpec.getSize(measureSpec);  
  48.   
  49.    
  50.   
  51. 依據specMode的值,如果是AT_MOST,specSize 代表的是最大可獲得的空間;如果是EXACTLY,specSize 代表的是精確的尺寸;如果是UNSPECIFIED,對於控制元件尺寸來說,沒有任何參考意義。  
  52.   
  53. 當以EXACT方式標記測量尺寸,父元素會堅持在一個指定的精確尺寸區域放置View。在父元素問子元素要多大空間時,AT_MOST指示者會說給我最大的範圍。在很多情況下,你得到的值都是相同的。  
  54.   
  55. 在兩種情況下,你必須絕對的處理這些限制。在一些情況下,它可能會返回超出這些限制的尺寸,在這種情況下,你可以讓父元素選擇如何對待超出的View,使用裁剪還是滾動等技術。  
  56.   
  57.  接下來的框架程式碼給出了處理View測量的典型實現:  
  58.   
  59.    
  60.   
  61. @Override  
  62.   
  63. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  64.   
  65. int measuredHeight = measureHeight(heightMeasureSpec);  
  66.   
  67. int measuredWidth = measureWidth(widthMeasureSpec);  
  68.   
  69. setMeasuredDimension(measuredHeight, measuredWidth);  
  70.   
  71. }  
  72.   
  73.    
  74.   
  75. private int measureHeight(int measureSpec) {  
  76.   
  77. int specMode = MeasureSpec.getMode(measureSpec);  
  78.   
  79. int specSize = MeasureSpec.getSize(measureSpec);  
  80.   
  81.    
  82.   
  83. // Default size if no limits are specified.  
  84.   
  85. int result = 500;  
  86.   
  87. if (specMode == MeasureSpec.AT_MOST)   
  88.   
  89. {  
  90.   
  91. // Calculate the ideal size of your  
  92.   
  93. // control within this maximum size.  
  94.   
  95. // If your control fills the available  
  96.   
  97. // space return the outer bound.  
  98.   
  99. result = specSize;  
  100.   
  101. }   
  102.   
  103. else if (specMode == MeasureSpec.EXACTLY)   
  104.   
  105. {  
  106.   
  107. // If your control can fit within these bounds return that value.  
  108.   
  109. result = specSize;  
  110.   
  111. }  
  112.   
  113. return result;  
  114.   
  115. }  
  116.   
  117.    
  118.   
  119. private int measureWidth(int measureSpec) {  
  120.   
  121. int specMode = MeasureSpec.getMode(measureSpec);  
  122.   
  123. int specSize = MeasureSpec.getSize(measureSpec);  
  124.   
  125.    
  126.   
  127. // Default size if no limits are specified.  
  128.   
  129. int result = 500;  
  130.   
  131. if (specMode == MeasureSpec.AT_MOST)  
  132.   
  133. {  
  134.   
  135. // Calculate the ideal size of your control  
  136.   
  137. // within this maximum size.  
  138.   
  139. // If your control fills the available space  
  140.   
  141. // return the outer bound.  
  142.   
  143. result = specSize;  
  144.   
  145. }   
  146.   
  147. else if (specMode == MeasureSpec.EXACTLY)   
  148.   
  149. {  
  150.   
  151. // If your control can fit within these bounds return that value.  
  152.   
  153. result = specSize;  
  154.   
  155. }  
  156.   
  157. return result;  
  158.   
  159. }  
  160.   
  161.    


getWidth得到是某個view的實際尺寸.

getMeasuredWidth是得到某view想要在parent view裡面佔的大小.


  1. getWidth在OnCreat的時候得到的是0. 當一個view物件建立時,android並不知道其大小,所以getWidth()和   getHeight()返回的結果是0,真正大小是在計算佈局時才會計算.

    2.  getMeasuredWidth必須在parent view或者它自己呼叫measure()函式之後才能得到. measure函式就是計算該函式需要佔用的空間大小.


    3.onMeasure會在onLayout之前呼叫


       4.如果ViewGroup中的View通過動畫移動了位置 需要呼叫requestLayout()重新定位View的位置;

相關文章