2012-04-25 70 views
1

我有我的應用程序的自定義視圖,我試圖每次更新文本OnDraw被調用。如何使用OnDraw中的canvas.drawText更新文本? Android

(一些)我的代碼lookes這樣的:

@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中相同的更新。爲什麼?怎麼修? Maby有比使用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; 
} 

}

回答

1

regenerateBackground()中刪除對drawTitle()的調用,並在您的setTitle()方法內調用invalidate。

+0

這只是使視圖重新生成所有的時間(並沒有打印任何東西)。我有一個呼叫,在drawHand內部無效.. – daker 2012-04-25 14:39:24

+0

有沒有其他建議? :) – daker 2012-04-25 14:47:56

+0

我的猜測是標題是你想定期更新的文本。通過調用invalidate觸發一個onDraw。而且,如果標題更改,則需要重新繪製,setTitle()是要調用invalidate的地方。此外,由於標題經常變化,它不應該成爲背景圖像的一部分。這就是爲什麼你應該從regenerateBackrgound()中刪除它。如果你在drawHand()中調用invalidate,你創建了一個無限循環的onDraw-> invalidate – Renard 2012-04-25 14:47:57