1

I'm looking for help with the following scaling problem.

I have built my own View class (custom view) which is a child of a Dialog. In this custom view I plot a graph in vertical direction from bottom to top. The graph can be greater or less than the size of the View. Therefore I would like to draw the graph onto the Canvas (which is greater than the View) using the onDraw() method (see code below) and later scale the Canvas to fit into the View.

Things I've tried already include using a ScaleAnimation with duration=0 or calling the canvas.scale() method. Everytime the same result; the graph is not scaled.

I already read different threads like:

How to resize a custom view programmatically?

Android scale view

Thank you for your help.

VerticalGraphView Code:

public class VerticalGraphView extends View {
    private static final String TAG = "VerticalGraphView";

    private int[] ch1_data = new int[1000];
    private int[] ch2_data = new int[1000];
    private int mCanvasHeight = 1000;
    private int mCanvasWidth = 242;
    private Paint ch1_color = new Paint();
    private Paint ch2_color = new Paint();
    private Paint zero_color = new Paint();
    private Paint grid_paint = new Paint();
    private Paint outline_paint = new Paint();

    public VerticalGraphView(Context context, AttributeSet attrs) {
        super(context, attrs);
        Log.d(TAG, "VerticalGraphView-Constructor called!");
    }

    protected void onFinishInflate() {
        super.onFinishInflate();
        Log.d(TAG, "onFinishInflate()-called!");

     // Log.i(TAG, "New Size set for height = " + setSizeHeight);
    }

    protected void onDraw(Canvas canvas) {
        Log.d(TAG, "onDraw()-called!");

     // // RESIZE TO FIT THE DATA
     // Bitmap b = Bitmap.createBitmap(mCanvasWidth, ch1_data.length, Bitmap.Config.ARGB_8888);
     // Canvas canvas = new Canvas(b);
     // canvas.setBitmap(b);

        ch1_color.setColor(Color.BLUE);                
        ch2_color.setColor(Color.RED);

        zero_color.setColor(Color.argb(80,0,0,00));
        zero_color.setStrokeWidth(3f);

        grid_paint.setColor(Color.rgb(200, 200, 200));

        outline_paint.setColor(Color.BLACK);
        outline_paint.setStrokeWidth(2f);

        if (canvas != null) {
            // Redraw the background
            canvas.drawRGB(255, 255, 255);

            // Draw vertical grey lines
            for (int vertical = 1; vertical<6; vertical++) {
                if (vertical == 3) { // Draw line in the middle
                    canvas.drawLine( vertical*(mCanvasWidth/6)+1, 1,
                                     vertical*(mCanvasWidth/6)+1, 
                                     mCanvasHeight+1,
                                     zero_color);
                } else {
                    canvas.drawLine( vertical*(mCanvasWidth/6)+1, 1,
                                     vertical*(mCanvasWidth/6)+1,
                                     mCanvasHeight+1,
                                     grid_paint);
                }
            }            

            // Draw horizontal grey lines
            for (int horizontal = 1; horizontal<10; horizontal++) {
                canvas.drawLine(1, horizontal*(mCanvasHeight/10)+1,
                                mCanvasWidth+1, 
                                horizontal*(mCanvasHeight/10)+1,
                                 grid_paint);
            }

            // draw outline
            canvas.drawLine(0, 0, (mCanvasWidth+1), 0, outline_paint); // top
            canvas.drawLine((mCanvasWidth), 0, (mCanvasWidth), (mCanvasHeight+1),
                            outline_paint);  //right
            canvas.drawLine(0, (mCanvasHeight), (mCanvasWidth), (mCanvasHeight),
                            outline_paint);    // bottom
            canvas.drawLine(0, 0, 0, (mCanvasHeight+1), outline_paint); //left

            // plot data
            int middle = mCanvasWidth / 2;

            for (int x=0; x<(ch2_data.length-1); x++) {                
                canvas.drawLine((middle + ch2_data[x]),(mCanvasHeight - x),
                                (middle + ch2_data[x+1]), 
                                (mCanvasHeight - x+1), 
                                ch2_color);
                canvas.drawLine((middle + ch1_data[x]),(mCanvasHeight - x),
                                (middle + ch1_data[x+1]), 
                                (mCanvasHeight - x+1), 
                                ch1_color);
            }
        }

        Log.e(TAG, "canvas.Height = " + canvas.getHeight());
        Log.e(TAG, "canvas.Width = " + canvas.getWidth());

        // RESIZE TO FIT THE VIEW, only in Y-Direction
        // Fits the canvas onto the view
        float ratio = ((float) canvas.getHeight()) / (float) mCanvasHeight;
        Log.e(TAG, "SCALE: ratio = " + ratio);

     // ScaleAnimation anim = new ScaleAnimation(1f,1f,1f,ratio, 0.5f, 0.5f);
     // anim.setDuration(1000);
     // this.startAnimation(anim);

     // canvas.scale(0f, ratio, canvas.getWidth() * 0.5f , canvas.getHeight() * 0.5f);

     // canvas.save(Canvas.MATRIX_SAVE_FLAG);
     // canvas.scale(0f, ratio, mCanvasWidth * 0.5f , mCanvasHeight * 0.5f);
     // canvas.restore(); 

     // canvas.scale(0f, 0.5f, mCanvasWidth * 0.5f , mCanvasHeight * 0.5f);
     // canvas.scale(100, 100);
     // canvas.getMatrix().postScale(0.5f, 0.5f);

        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(242, 500);
     // params.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE); 
        params.addRule(RelativeLayout.CENTER_IN_PARENT);
        this.setLayoutParams(params);

     // RelativeLayout layout = (RelativeLayout) findViewById(R.id.relativeLayoutRight);
     // ViewGroup.LayoutParams params = layout.getLayoutParams();
     // params.height = 500;
     // params.width = canvas.getWidth();
     // layout.setLayoutParams(params);
     // invalidate();

     // DRAW THE CANVAS
        super.onDraw(canvas);
    }        

    public void setData(int[] data1, int[] data2 ) {
        Log.d(TAG, "setData()-called!");
        ch1_data = data1;
        ch2_data = data2;
    }

    /**
     * This method sets the height of the View.</br>
     * <b><u>NOTE:</u></b> The method call deletes all data stored for the graph.
     * @param newHeight the new height of the view
     */

    public void setHeight(int newHeight) {
        mCanvasHeight = newHeight;
        ch1_data = new int[newHeight];
        ch2_data = new int[newHeight];
    }
}

layout.xml which is used in the Dialog:

<com.android.Ui.VerticalGraphView 
    android:id="@+id/verticalGraphView"
    android:layout_width="242dp"
    android:layout_height="1000dp"
    android:layout_centerInParent="true" />
Community
  • 1
  • 1
milius
  • 93
  • 2
  • 5

1 Answers1

0
  1. you are not supposed to change the layout in the onDraw() method. in the onDraw method you have to take the current layout state and deal with it (and draw inside its boundaries).

  2. try to calculate the needed size of the view , and then set the layout params . upon each time you need to scale , do it again . if an update is needed , call invalidate() .

android developer
  • 114,585
  • 152
  • 739
  • 1,270
  • Thank you for your answer. Just for clarity, is it correct that I should try to set the size of the view to the size which is needed by the given data. In the example I would set the size via LayoutParams to 1000. After that I can draw onto the canvas. At last I reset the size of the view via LayoutParams to the size I want (scaling is implicitly done) and I call invalidate() to make the changes visible? Correct? – milius Jun 19 '12 at 06:18
  • not sure i understand . why would you like to change the size of the view twice ? if you know what should be the size , simply change it once (using setLayoutParams) and that's it . if you need to change it again in the future , calculate the needed size, and set it again. – android developer Jun 19 '12 at 07:30
  • I just want to use the setSize-machanism to draw onto a canvas which is greater than the size of the view i want to show because i draw on every pixel on the big(1000px) canvas. The view later is smaller (50% or so). Now I set the LayoutParams to the size of the data which is 1000 and I reset the LayoutParams in the onDraw() at the end. (I never call invalidate() because I am already executing the onDraw()-method). The Problem still is that the graph is just cut off but not scaled to the correct size. – milius Jun 19 '12 at 07:35
  • now i see . so how about draw whatever you want to a large bitmap , and during the onDraw , you take only the part of the bitmap that is interesting for the view ? the view doesn't need to draw into areas that the end user cannot see (outside of the screen , for example) . – android developer Jun 19 '12 at 07:58
  • Drawing to a large bitmap would be nice if i can scale it in the onDraw to the size i need. I need the whole graph/whole bitmap but scaled. The user should see the hole graph but it should be scaled to the right size which is already given by the LayoutParams of the View. – milius Jun 19 '12 at 11:19