View的繪制可以分為下面三個過程:
1、Measure
此處View有基本實現(xiàn)
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
????setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
????getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
public static int getDefaultSize(int size, int measureSpec) {
????int result = size;
????int specMode = MeasureSpec.getMode(measureSpec);
????int specSize = MeasureSpec.getSize(measureSpec);
????switch (specMode) {
????????caseMeasureSpec.UNSPECIFIED:
????????????result = size;
????????break;
????caseMeasureSpec.AT_MOST:
????caseMeasureSpec.EXACTLY:
????????????result = specSize;
????????break;
????}
????return result;
}
UNSPECIDIED 父容器不對view有任何限制,要多大有多大,一般用于系統(tǒng)內(nèi)部測量。
EXACTLY對應(yīng)的是LayoutParams的match_parent和具體數(shù)值(xxxdp),表示父容器已經(jīng)檢測出view的大小。
AT_MOST對應(yīng)的是LayoutParams的wrap_content,父容器指定了可用的大小。
2、Layout
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
}
沒有子View需要排列,所以這一步其實我們不需要做額外的工作。插一句,對ViewGroup類,onLayout方法中,我們需要將所有子View的大小寬高設(shè)置好
3、Draw
protected void onDraw(Canvas canvas) {
}
例:循環(huán)調(diào)用了ondrow,寫著玩的當(dāng)不得真
protected void onDraw(Canvas canvas) {
????super.onDraw(canvas); //get screen width
????float sw = this.getMeasuredWidth();
????if (startX >= sw + (hSpace + space) - (sw % (hSpace + space))) {
????????startX = 0;
????} else {
????????startX += delta; }
????float start = startX; // draw latter parse
????while (start < sw) {
????????canvas.drawLine(start, 5, start + hSpace, 5, mPaint); start += (hSpace + space);
????}
????start = startX - space - hSpace; // draw front parse
????while (start >= -hSpace) {
????????canvas.drawLine(start, 5, start + hSpace, 5, mPaint); start -= (hSpace + space);
????}
????if (index >= 700000) {
????????index = 0;
????}
invalidate();
}
三個重要的方法
requestLayout View重新調(diào)用一次layout過程。
invalidate View重新調(diào)用一次draw過程
forceLayout 標識View在下一次重繪,需要重新調(diào)用layout過程。