我的应用程序有一个自定义视图,并且每次调用 OnDraw 时我都会尝试更新文本。
(一些)我的代码如下所示:
@Override
protected void onDraw(Canvas canvas) {
Log.e(TAG,"onDraw");
drawBackground(canvas);
float scale = (float) getWidth();
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.scale(scale, scale);
drawTitle(canvas);
drawHand(canvas);
canvas.restore();
if (handNeedsToMove()) {
moveHand();
}
}
private void drawTitle(Canvas canvas) {
String title = getTitle();
Log.i("drawtitle",title);
titlePaint = new Paint();
titlePaint.setColor(0xffffffff);
titlePaint.setAntiAlias(true);
titlePaint.setTypeface(Typeface.MONOSPACE);
titlePaint.setTextAlign(Paint.Align.CENTER);
titlePaint.setTextSize(0.05f);
titlePaint.setTextScaleX(0.8f);
canvas.drawText(title, 0.45f, 0.95f, titlePaint);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Log.d(TAG, "Size changed to " + w + "x" + h);
regenerateBackground();
}
private void regenerateBackground() {
if (background != null) {
background.recycle();
}
//Some stuff here
drawInstruments(backgroundCanvas);
drawTitle(backgroundCanvas);
}
文本在被 regenerateBackground 调用时得到更新,但在 OnDraw 上保持不变。为什么?怎么修?也许有比使用 canvas.drawText 更好的方法吗?我正在制作一个速度计,我只想打印“针”指向的值......
编辑:完整代码
公共最终类仪表板扩展视图 {
private static final String TAG = Dashboard.class.getSimpleName();
// drawing tools
private Paint dashPaint;
private static Bitmap dash;
private Matrix dashMatrix;
private float dashScalex;
private float dashScaley;
private Paint handPaint;
private Path handPath;
private Paint handScrewPaint;
private Paint backgroundPaint;
// end drawing tools
private Bitmap background; // holds the cached static part
private Paint titlePaint;
private Path titlePath;
// scale configuration
private static final int totalNicks = 100;
private static final float degreesPerNick = 360.0f / totalNicks;
private static final int centerDegree = 40; // the one in the top center (12 o'clock)
private static final int minDegrees = -30;
private static final int maxDegrees = 110;
// hand dynamics -- all are angular expressed in F degrees
private boolean handInitialized = true;
private float handPosition = centerDegree;
private float handTarget = centerDegree;
private float handVelocity = 0.0f;
private float handAcceleration = 0.0f;
private long lastHandMoveTime = -1L;
private static float circlePosx = 0.5f;
private static float circlePosy = 0.36f;
private static float circleRadius = 0.1f;
public Dashboard(Context context) {
super(context);
init();
}
public Dashboard(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public Dashboard(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
Bundle bundle = (Bundle) state;
Parcelable superState = bundle.getParcelable("superState");
super.onRestoreInstanceState(superState);
handInitialized = bundle.getBoolean("handInitialized");
handPosition = bundle.getFloat("handPosition");
handTarget = bundle.getFloat("handTarget");
handVelocity = bundle.getFloat("handVelocity");
handAcceleration = bundle.getFloat("handAcceleration");
lastHandMoveTime = bundle.getLong("lastHandMoveTime");
}
@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
Bundle state = new Bundle();
state.putParcelable("superState", superState);
state.putBoolean("handInitialized", handInitialized);
state.putFloat("handPosition", handPosition);
state.putFloat("handTarget", handTarget);
state.putFloat("handVelocity", handVelocity);
state.putFloat("handAcceleration", handAcceleration);
state.putLong("lastHandMoveTime", lastHandMoveTime);
return state;
}
public static float[] getCircle(){
float[] circle = {circlePosx,circlePosy,circleRadius};
return circle;
}
public static int[] getCanvasSize(){
int[] size = {dash.getWidth(),dash.getHeight()};
return size;
}
private void init() {
initDrawingTools();
}
private void initDrawingTools() {
/******/
dashPaint = new Paint();
dashPaint.setFilterBitmap(true);
dash = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.dashboard);
dashMatrix = new Matrix();
dashScaley = 1f/dash.getHeight();// * 0.3f;;
dashScalex = 1f/dash.getWidth();
dashMatrix.setScale(dashScalex, dashScaley);
Log.i("dash width", "= "+dash.getWidth()+" - "+getWidth());
Log.i("dash height", "= "+dash.getHeight());
Log.i("dash scale x ", "= "+1f/dash.getHeight());
Log.i("dash scale y ", "= "+dashScaley);
/******/
handPaint = new Paint();
handPaint.setAntiAlias(true);
handPaint.setColor(0xffff0000);
handPaint.setShadowLayer(0.01f, -0.005f, -0.005f, 0x7f000000);
handPaint.setStyle(Paint.Style.FILL);
handPath = new Path();
handPath.moveTo(circlePosx-0.01f, circlePosy+0.06f);
handPath.lineTo(circlePosx, circlePosy - 0.16f);
handPath.lineTo(circlePosx+0.01f, circlePosy + 0.06f);
handPath.addCircle(circlePosx, circlePosy, 0.025f, Path.Direction.CW);
handScrewPaint = new Paint();
handScrewPaint.setAntiAlias(true);
handScrewPaint.setColor(0xf0000021);
handScrewPaint.setStyle(Paint.Style.FILL);
backgroundPaint = new Paint();
backgroundPaint.setFilterBitmap(true);
titlePaint = new Paint();
titlePaint.setColor(0xffffffff);
titlePaint.setAntiAlias(true);
titlePaint.setTypeface(Typeface.DEFAULT_BOLD);
titlePaint.setTextAlign(Paint.Align.CENTER);
titlePaint.setTextSize(0.05f);
titlePaint.setTextScaleX(0.8f);
titlePath = new Path();
titlePath.moveTo(0.5f, 0.8f);
titlePath.lineTo(0.6f, 0.8f);
//titlePath = new Path();
//titlePath.addArc(new RectF(0.24f, 0.24f, 0.76f, 0.76f), -180.0f, -180.0f);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.d(TAG, "Width spec: " + MeasureSpec.toString(widthMeasureSpec));
Log.d(TAG, "Height spec: " + MeasureSpec.toString(heightMeasureSpec));
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int chosenWidth = chooseDimension(widthMode, widthSize);
int chosenHeight = chooseDimension(heightMode, heightSize);
setMeasuredDimension(chosenWidth, chosenHeight);
//int chosenDimension = Math.min(chosenWidth, chosenHeight);
//setMeasuredDimension(chosenDimension, chosenDimension);
}
private int chooseDimension(int mode, int size) {
if (mode == MeasureSpec.AT_MOST || mode == MeasureSpec.EXACTLY) {
return size;
} else { // (mode == MeasureSpec.UNSPECIFIED)
return getPreferredSize();
}
}
// in case there is no size specified
private int getPreferredSize() {
return 600;
}
private int nickToDegree(int nick) {
int rawDegree = ((nick < totalNicks / 2) ? nick : (nick - totalNicks)) * 2;
int shiftedDegree = rawDegree + centerDegree;
return shiftedDegree;
}
private float degreeToAngle(float degree) {
return (degree - centerDegree) / 2.0f * degreesPerNick;
}
private void drawInstruments(Canvas canvas){
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.translate(0.5f - dash.getWidth() * dashScalex / 2.0f,
0.5f - dash.getHeight() * dashScaley / 2.0f);
//canvas.drawBitmap(dash, 0, 0, dashPaint);
canvas.drawBitmap(dash, dashMatrix, dashPaint);
canvas.restore();
}
private void drawHand(Canvas canvas) {
Log.e(TAG, "drawHand");
if (handInitialized) {
float handAngle = degreeToAngle(handPosition);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.rotate(handAngle, circlePosx, circlePosy);
canvas.drawPath(handPath, handPaint);
canvas.restore();
canvas.drawCircle(0.5f, 0.36f, 0.01f, handScrewPaint);
}
}
private String getTitle(){
return String.valueOf(handPosition);
}
private void drawTitle(Canvas canvas) {
String title = getTitle();
//canvas.drawTextOnPath(title, titlePath, 0.0f,0.0f, titlePaint);
//canvas.drawPaint(titlePaint);
Log.i("drawtitle",title);
canvas.drawText(title, 0.45f, 0.95f, titlePaint);
//invalidate();
}
private void drawBackground(Canvas canvas) {
if (background == null) {
Log.w(TAG, "Background not created");
} else {
canvas.drawBitmap(background, 0, 0, backgroundPaint);
}
}
@Override
protected void onDraw(Canvas canvas) {
Log.e(TAG,"onDraw");
drawBackground(canvas);
float scale = (float) getWidth();
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.scale(scale, scale);
drawTitle(canvas);
drawHand(canvas);
canvas.restore();
if (handNeedsToMove()) {
moveHand();
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
Log.d(TAG, "Size changed to " + w + "x" + h);
regenerateBackground();
}
private void regenerateBackground() {
// free the old bitmap
if (background != null) {
background.recycle();
}
Log.e("Width="+getWidth(), "Height="+getHeight());
background = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas backgroundCanvas = new Canvas(background);
float scalex = (float) getWidth();
float scaley = (float) getHeight();
backgroundCanvas.scale(scalex, scaley);
drawInstruments(backgroundCanvas);
}
private boolean handNeedsToMove() {
return Math.abs(handPosition - handTarget) > 0.01f;
}
private void moveHand() {
Log.e(TAG, "moveHand!!");
if (! handNeedsToMove()) {
return;
}
if (lastHandMoveTime != -1L) {
long currentTime = System.currentTimeMillis();
float delta = (currentTime - lastHandMoveTime) / 1000.0f;
float direction = Math.signum(handVelocity);
if (Math.abs(handVelocity) < 90.0f) {
handAcceleration = 5.0f * (handTarget - handPosition);
} else {
handAcceleration = 0.0f;
}
handPosition += handVelocity * delta;
handVelocity += handAcceleration * delta;
if ((handTarget - handPosition) * direction < 0.01f * direction) {
handPosition = handTarget;
handVelocity = 0.0f;
handAcceleration = 0.0f;
lastHandMoveTime = -1L;
} else {
lastHandMoveTime = System.currentTimeMillis();
}
invalidate();
} else {
lastHandMoveTime = System.currentTimeMillis();
moveHand();
}
}
private float getRelativeTemperaturePosition() {
if (handPosition < centerDegree) {
return - (centerDegree - handPosition) / (float) (centerDegree - minDegrees);
} else {
return (handPosition - centerDegree) / (float) (maxDegrees - centerDegree);
}
}
public void setHandTarget(float temperature) {
Log.e(TAG, "setHandTarget!");
if (temperature < minDegrees) {
temperature = minDegrees;
} else if (temperature > maxDegrees) {
temperature = maxDegrees;
}
handTarget = temperature;
Log.e(TAG, "handTarget="+handTarget);
handInitialized = true;
invalidate();
}
public float getHandTarget(){
return handTarget;
}
}