一個倒計時控件:CountView extend JustifyTextView extend ImageView,CountView倒計時觸發後,調用JustifyTextView中的方法setText(String text);使用invalidate(),進行重繪,而不是使用TextView setText(),調用requestLayout進行重繪,原因是:requestLayout()方法會一層一層調用父佈局的:requestLayout()(會導致父佈局重新進行測量、佈局和繪製流程,這樣會影響某些View不能正常顯示:例如滑動顯示菜單,佈局變動時會自動關閉菜單顯示,這不是我想要的結果),而invalidate()只針對當前變動的View進行重繪
主要問題:第一個方法會不斷調用,第一次調用後會調用onDraw方法,但是UI上沒顯示畫的結果,並且隨後再也不調用onDraw方法
//JustifyTextView.java 一秒調用一次
public void setText(String text) {
this.text = text;
invalidate();
}
//正常情況下每次調用invalidate();會調用下面的方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (paint == null){
initPaint();
}
Paint.FontMetrics fm = paint.getFontMetrics();
float baseline = fm.descent - fm.ascent;
canvas.drawText(text, desiredWidth/2, baseline, paint);
}
分析問題可能產生的原因:
- onDraw沒調用是因爲 invalidate(),調用不對?換做下面幾個方法都不行,看來不是這個問題
requestLayout();
((View)getParent()).invalidate();
forceLayout();
- 嘗試在子View(CountView)中進行繪製,仍然只繪製一次
- 對ImageView設置背景,仍然無果
- 對View繪製的起始座標進行多次設置嘗試,仍然不行
canvas.drawText(text, x, y, paint);
- 改變xml佈局中控件的wrap_content爲指定寬高,終於顯示出來
android:layout_width="wrap_content"
android:layout_height="wrap_content"
# 改爲
android:layout_width="100dp"
android:layout_height="100dp"
最後
- 通過重新實現onMeasure方法(xml中仍然採用wrap_content),動態設置View的寬高,達到正常顯示的效果
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
//Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
//Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else {
//Be whatever you want
width = desiredWidth;
}
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(desiredHeight, heightSize);
} else {
//Be whatever you want
height = desiredHeight;
}
//MUST CALL THIS
setMeasuredDimension(width, height);
}