Amazon Gift Cards

Tuesday, December 14, 2010

Previewing while Drawing with Canvas in Android

After my site being gone from the web yesterday, its back :) it happens to be a blogger bug. Anyway i got a lot of request on how to preview your drawing, and continue our Drawing with Canvas series, here is how to preview while drawing.

Notes
• The files are uploaded in http://goo.gl/ecHpE
• The project was build in IntelliJ and it should be easy to import to Eclipse

What Do I Need
DrawingSurface
public class DrawingSurface extends SurfaceView implements SurfaceHolder.Callback {
  public boolean isDrawing = true;
  public DrawingPath previewPath;

  private Handler previewDoneHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
      isDrawing = false;
    }
  };

  class DrawThread extends Thread{
    @Override
    public void run() {
      commandManager.executeAll(c,previewDoneHandler);
      previewPath.draw(c);
    }
  };
}



Drawing Activity
public class DrawingActivity extends Activity implements View.OnTouchListener{
  public void onCreate(Bundle savedInstanceState) {
    drawingSurface.previewPath = new DrawingPath();
    drawingSurface.previewPath.path = new Path();
    drawingSurface.previewPath.paint = getPreviewPaint();
    ...
  }
  private Paint getPreviewPaint(){
    final Paint previewPaint = new Paint();
    previewPaint.setColor(0xFFC1C1C1);
    previewPaint.setStyle(Paint.Style.STROKE);
    previewPaint.setStrokeJoin(Paint.Join.ROUND);
    previewPaint.setStrokeCap(Paint.Cap.ROUND);
    previewPaint.setStrokeWidth(3);
    return previewPaint;
  }

  public boolean onTouch(View view, MotionEvent motionEvent) {
    if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){
      currentBrush.mouseDown(drawingSurface.previewPath.path, motionEvent.getX(), motionEvent.getY());
    }else if(motionEvent.getAction() == MotionEvent.ACTION_MOVE){
      currentBrush.mouseMove(drawingSurface.previewPath.path, motionEvent.getX(), motionEvent.getY());
    }else if(motionEvent.getAction() == MotionEvent.ACTION_UP){
      currentBrush.mouseUp(drawingSurface.previewPath.path, motionEvent.getX(), motionEvent.getY());
      drawingSurface.previewPath.path = new Path();
    }
  }
}



Quick Explanation
Ads from Amazon:
Explanation
public boolean isDrawing = true;
Lets introduce something that would tell our app if we are drawing or not.

public DrawingPath previewPath;
Here we create another DrawingPath which would only do the preview for us

private Handler previewDoneHandler = new Handler(){
  @Override
  public void handleMessage(Message msg) {
    isDrawing = false;
  }
};

Here we create a handler to tell our app to stop drawing at the end of the last path it has drawn (this function should named differently, ahhah)

class DrawThread extends Thread{
  @Override
  public void run() {
    commandManager.executeAll(c,previewDoneHandler);
    previewPath.draw(c);
  }
};

Here you draw the preview path and pass our complete handler to stop our app from drawing over and over

public void onCreate(Bundle savedInstanceState) {
  drawingSurface.previewPath = new DrawingPath();
  drawingSurface.previewPath.path = new Path();
  drawingSurface.previewPath.paint = getPreviewPaint();
  ...
private Paint getPreviewPaint(){
  ...
}

Here we just initialize the previewPath with a different path (a kinda gray paint, 0xFFC1C1C1)

public boolean onTouch(View view, MotionEvent motionEvent) {
  if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){
nbsp;   currentBrush.mouseDown(drawingSurface.previewPath.path, motionEvent.getX(), motionEvent.getY());
  }else if(motionEvent.getAction() == MotionEvent.ACTION_MOVE){
    currentBrush.mouseMove(drawingSurface.previewPath.path, motionEvent.getX(), motionEvent.getY());
  }else if(motionEvent.getAction() == MotionEvent.ACTION_UP){
    currentBrush.mouseUp(drawingSurface.previewPath.path, motionEvent.getX(), motionEvent.getY());
    drawingSurface.previewPath.path = new Path();
  }
}

Here we use the concept we understood from brushes Read the explanation here

Hope this helps :)

10 comments:

Anonymous said...

Awesome work..it is really helpful to fix my bugs and thats what im looking for. Thanks for your blog post and everything...

Unknown said...

Great tutorial, it helps a lot, Thanks.
One question, when I run it in my emulator, which is set to have a 10 inch screen, your app only take about 1/5 of the whole screen. I been unable to adjust that, how would you fix that?

Thanks!

Anonymous said...

Great work. I having been playing with it. Currently the background is black on the bitmap. Anyway to make it white?

monmonja said...

ya do soemthing like
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
canvas.drawColor(backgroundColor);

John said...

Hi sir, where do I put
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
canvas.drawColor(backgroundColor);?
thanks..

monmonja said...

@john place it on DrawingSurface's DrawThread class under run() function, you could check out the codes on https://sites.google.com/site/tutorialsformobileprogramming/android-tutorials/android-files

John said...

thanks a lot for your quick response sir. you inspire me. :)

John said...

Hi sir, my DrawingActivity.java says 'R cannot be resolved to a variable',in eclipse all R.variable is red underlined like in R.layout.drawing_activity, any ideas? I tried to clean and rebuild the project but the problem persists..

Andrea said...

Hi Sir , thank you for your useful tutorial : ) I have try to add a background , like that : drawingSurface.setBackgroundResource(R.drawable.bg);

The Background changes. However, the Background cover all the drawing. How could I set the background?Thank for help: )

Anonymous said...

Thanks for the tutorial. Got a question when previewing the path: since I want the preview path to be the same color as the actually path, I simply set the preview paint color to be the same. However, after the number of paths continue to increase, there is a "flicker" between the preview path and the actual path. Is there anyway to get rid of that?

Thanks!