Draw line using finger on Canvas in Android

Draw line on canvas using finger
Draw line on canvas using finger

Draw line on canvas using your finger is very much important task if you are going to develop any kind of drawing app or image editing app. So in this tutorial we are going to see how one can draw on canvas using touch methods.

(Those who want to just copy paste the whole class can scroll at the end!)

First of all we create a custom view which contains the canvas and all its touch methods which performs the draw activity.

This is the class which we are going to use in XML layout. You can use it in XML like this . Here we are going to add all the initialization in the second constructor as we are going to use it in the XML file. But it is advisable if you use a common method and add it to every constructor.

public class DrawLineCanvas extends View {

  public DrawLineCanvas(Context context) {
    super(context);
  }

  public DrawLineCanvas(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public DrawLineCanvas(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }

}

Now we add few methods in the above class, each method has different purpose of its own.

This method will give us the width and height of the view that is inflated. So if we give “match_parent” in the XML file then we can get the full width and height of the view and create bitmap and canvas of that size so that we can draw on whole visible area of the screen except toolbar and status bar.

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  super.onSizeChanged(w, h, oldw, oldh);
}

Now this method will identify the touch event and draw on the bitmap accordingly. We consider three different events here. One is when user touch the screen, second when the user move his/her finger on the screen and the last one when the user lift the finger from the screen.

@Override
public boolean onTouchEvent(MotionEvent event) {

  switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
      break;
    case MotionEvent.ACTION_MOVE:
      break;
    case MotionEvent.ACTION_UP:
      break;
    default:
      return false;
  }

  invalidate();
  return true;
}

Here “invalidate()” calls the below method so it will draw on the canvas.

The below method will draw the path(which we drew using finger) on the canvas. We will call this method every time we touch or drag finger on the screen.

@Override
protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
}

Now we initialise all the needed things to get started.

private Canvas c;

private Paint pLine, pBg;
private Path touchPath;

private Bitmap b;

public DrawLineCanvas(Context context, AttributeSet attrs) {
  super(context, attrs);

  pBg = new Paint();
  pBg.setColor(Color.WHITE);

  pLine = new Paint();
  pLine.setColor(Color.GREEN);
  pLine.setAntiAlias(true);
  pLine.setStyle(Paint.Style.STROKE);
  pLine.setStrokeWidth(12);

  touchPath = new Path();
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  super.onSizeChanged(w, h, oldw, oldh);
  b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
  c = new Canvas(b);
}

Here Canvas is used to save the drawing when we lift the finger and started drawing again. Paint is for line that is being drawn and the background on which the line is being drawn. It includes the line size, color, stroke, etc. Path is for saving the path that we create by moving our finger on the screen. So when we lift the finger we will draw this path to our canvas and it will be drawn on the screen. And lastly the Bitmap is used to initialise our canvas with the size we are getting from the view inflated in the XML using method onSizeChanged().

Now comes the drawing part, now we will identify the touch event and save it to the “touchPath” we initialised so that we can draw it to the canvas once we lift the finger. On every action event, we also calls the “invalidate()” method so that your current moving path will be drawn on the canvas.

@Override
public boolean onTouchEvent(MotionEvent event) {

  float touchX = event.getX();
  float touchY = event.getY();
  switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
      touchPath.moveTo(touchX, touchY);
      break;
    case MotionEvent.ACTION_MOVE:
      touchPath.lineTo(touchX, touchY);
      break;
    case MotionEvent.ACTION_UP:
      touchPath.lineTo(touchX, touchY);
      c.drawPath(touchPath, pLine);
      touchPath = new Path();
      break;
    default:
      return false;
  }

  invalidate();
  return true;
}

Here in “ACTION_UP” event we draw the path “touchPath” to the Canvas c and reset the path so you can start new line when you again start drawing something.

Now finally the “onDraw()” method which will draw everything on canvas and you can see your drawing on screen!

@Override
protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);

  canvas.drawBitmap(b, 0, 0, pBg);
  canvas.drawPath(touchPath, pLine);
}

The complete class looks like this.

public class DrawLineCanvas extends View {

  private Canvas c;

  private Paint pLine, pBg;
  private Path touchPath;

  private Bitmap b;

  public DrawLineCanvas(Context context) {
    super(context);
  }

  public DrawLineCanvas(Context context, AttributeSet attrs) {
    super(context, attrs);

    pBg = new Paint();
    pBg.setColor(Color.WHITE);

    pLine = new Paint();
    pLine.setColor(Color.GREEN);
    pLine.setAntiAlias(true);
    pLine.setStyle(Paint.Style.STROKE);
    pLine.setStrokeWidth(12);

    touchPath = new Path();
  }

  public DrawLineCanvas(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }

  @Override
  protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    c = new Canvas(b);
  }
  
  @Override
  public boolean onTouchEvent(MotionEvent event) {

    float touchX = event.getX();
    float touchY = event.getY();
    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
        touchPath.moveTo(touchX, touchY);
        break;
      case MotionEvent.ACTION_MOVE:
        touchPath.lineTo(touchX, touchY);
        break;
      case MotionEvent.ACTION_UP:
        touchPath.lineTo(touchX, touchY);
        c.drawPath(touchPath, pLine);
        touchPath = new Path();
        break;
      default:
        return false;
    }

    invalidate();
    return true;
  }

  @Override
  protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    canvas.drawBitmap(b, 0, 0, pBg);
    canvas.drawPath(touchPath, pLine);
  }
}

To save this canvas as image on your sdcard, please check my other post here: https://acomputerengineer.wordpress.com/2015/01/13/how-to-draw-canvas-on-imageview-and-save-canvas-as-bitmap-and-store-in-sdcard-in-android/

For source code, please checkout my Github repo here: https://github.com/dakshbhatt21/a-computer-engineer

Draw line on Canvas in Android

You can draw different type of line on Canvas in Android. You can change it’s color, stroke, effect, etc. Here we will see the basics of drawing line on Canvas.

Checkout the basics of Canvas if you are new to Canvas: Draw Canvas on ImageView

Here is the example of different parameters you can apply to draw a line on Canvas in Android.

device-2016-08-23-003351
Draw line on Canvas
//simple line
Paint p1 = new Paint();
p1.setAntiAlias(true);
p1.setColor(Color.BLACK);
p1.setStrokeWidth(10);
canvas.drawLine(10, 40, 400, 40, p1);

//line with color
Paint p2 = new Paint();
p2.setAntiAlias(true);
p2.setColor(Color.RED);
p2.setStrokeWidth(10);
canvas.drawLine(10, 80, 400, 80, p2);

//line with round ends
Paint p3 = new Paint();
p3.setAntiAlias(true);
p3.setColor(Color.BLUE);
p3.setStrokeWidth(10);
p3.setStrokeCap(Paint.Cap.ROUND);
canvas.drawLine(10, 120, 400, 120, p3);

//slanted line
Paint p4 = new Paint();
p4.setAntiAlias(true);
p4.setColor(Color.GREEN);
p4.setStrokeWidth(10);
canvas.drawLine(10, 160, 400, 200, p4);

Here we use AntiAlias flag to true to remove distortion in the lines.