2

I am trying to do a simple paint application, but every time I call onDraw it erases what I had there previously. In my on draw I am doing the following (where point is a class with an x and y int, and "points" is a list points):

        Paint paint = new Paint();
        int c = getPaintFromActivityClass();
        paint.setColor(c);
        Path path = new Path();
        boolean first = true;
        for(Point point : points){
            if(first){
                first = false;
                path.moveTo(point.x, point.y);
            }
            else{
                path.lineTo(point.x, point.y);
            }
        }
        canvas.drawPath(path, paint);

I tried adding the "old" path to a new path each time, essentially concatenating the paths to each other and it created separate (not connected) paths. However, in onDraw I am also setting the paint color which is being changed by another view. When I added the paths to each other, changing the color changed the color of all the paths.

mergesort
  • 5,087
  • 13
  • 38
  • 63

2 Answers2

2

Are you calling super.onDraw(canvas)? If so, do all of your drawing after that otherwise the super call will redraw the entire view.

If you're using onTouch, I also guess you're doing panning and/or zooming. If so, then also use canvas.save() before you do any drawing and canvas.restore() afterwards. The Android canvas is similar to the HTML5 canvas and this description is better than the Android docs (as is just about any other programming topic page on the internet ;))

https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Transformations

Rodia
  • 1,407
  • 8
  • 22
  • 29
Simon
  • 14,407
  • 8
  • 46
  • 61
  • No panning or zooming. Also I am not calling super.onDraw(canvas). I still cannot seem to get it working. I am not sure where to set the bitmap and where to draw it from either. – mergesort Apr 17 '12 at 21:13
  • 1
    OK, first things first. However you achieve it, you must draw everything in onDraw. It is not additive so, either you have to concatenate stuff, as you say, or store previous draws. One pattern for this is to get the last frame drawn (e.g. ImageView.getBackgroundDrawable(), drawing your new stuff on it then drawing the bitmap to the canvas. Does this help ... http://www.tutorialforandroid.com/2009/06/drawing-with-canvas-in-android.html – Simon Apr 17 '12 at 21:21
  • Thanks for the comment. Understanding that you must redraw everything in onDraw made things make more sense. I've entirely completed what I need to do. Thanks! – mergesort Apr 17 '12 at 23:47
2

Another option is to create an ArrayList or Vector of paths and colors and store each, then change your onDraw method. Add these to the class:

ArrayList<Path> paths;
ArrayList<int> colors;

In onTouch you would create and add a path and color to each ArrayList, and then in ondraw traverse the path...still calling invalidate in your ontouch method. To start over you would empty the ArrayList

Paint paint = new Paint();
for(int i =0 : i < Paths.size() ;i++){ 
paint.setColor(colors.get(i));
canvas.drawPath(paths.get(i), paint);
}

If you create a bunch of bitmaps make sure you recycle them at the right time. The concept in this answer may be better if you want to track the history, it would be easy to do a simple "undo" button and just pop out the last entry. You could further refine this by creating your own class to track color and paths and then you would only have one ArrayList of your custom class.

Nick
  • 351
  • 1
  • 8