現(xiàn)實生活中,如果我們要去畫一個圖形,就必須知道它的位置和大小。
Android系統(tǒng)在繪制View前,也必須對View進行測量,這個過程在onMeasure()方法中進行。
MeaSureSpec
Android 提供的測量View的一個類,是一個32位int值,其中高2位為測量模式,低30位為測量大小(size)。
測量模式可分為3類:
- EXACTLY
精確值模式:將layout_width或layout_height屬性指定為具體數(shù)值(30dp)或者match_parent - AT_MOST
最大值模式:將layout_width或layout_height指定為wrap_content。 - UNSPECIFIED
View想多大就多大。通常在自定義View才會使用。
注意:
View的默認哦那Measure()只支持EXACTLY,
如果讓自定的view支持wrap_content,必須重寫onMeasure()來指定wrap_content大小。
簡單示例:
public class MeasuredView extends View {
public MeasuredView(Context context) {
super(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 調(diào)用父類的onMeasure()
super.onMeasure(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
// 或者直接調(diào)用父類的setMeasuredDimension(),因為父類的onMeasure()最終調(diào)用了setMeasuredDimension()
// setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}
/**
* 測量View的width
* @param measureSpec MeasureSpec對象
* @return View的width
*/
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = 200;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
/**
* 測量View的height
* @param measureSpec MeasureSpec對象
* @return View的height
*/
private int measureHeight(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = 200;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
}
View的繪制
2D繪圖必備利器——Canvas
獲取Canvas對象的方式:
a. 由方法中的參數(shù)傳入,例如,View的onDraw()中有一個參數(shù)就是Canvas對象
b. 通過構(gòu)造方法構(gòu)造,即:Canvas canvas = new Canvas(bitmap),在Canvas的構(gòu)造方法傳入一個Bitmap對象,即可獲取一個Canvas對象。通過傳入Bitmap對象構(gòu)造Canvas對象的過程稱為“畫布的裝載”,傳入的Bitmap對象承載了多有繪制在Canvas上的像素信息,調(diào)用Canvas.drawXXX方法(如:Canvas.drawBitmap(bitmap, 0, 0, null))都將發(fā)生在該Bitmap對象上。
利用Canvas繪圖
a. 通過Canvas.drwaXXX進行繪制操作將直接作用于Bitmap對象,當再次刷新View的時候,我們將會被繪制的Bitmap對象發(fā)生了改變;
b. 利用Canvas和Paint進行繪圖;
c. 不管多么復雜、精美的空間,都可以被拆分為一個個小的圖形單元,我們只要找到這些圖形單元,就可以將控件繪制出來。
參考:Android群英傳
Android視圖控件架構(gòu)分析之View、ViewGroup