1

我的应用程序有一个自定义视图,并且每次调用 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;
}

}

4

1 回答 1

1

在您的 setTitle() 方法中删除对drawTitle()fromregenerateBackground()和调用 invalidate 的调用。

于 2012-04-25T14:33:55.820 回答