Persional Information

Drawing with Canvas in Android Renewed

Update - Nov 21, 2010Created a series over this topic over at Drawing with Canvas Series, more articles would appear in the future :)

Back one year ago, i blogged about Drawing with Canvas in Android, at that time i was creating a drawing app that never get released (lazy me). Now im planning to redo everything and share my learnings as i go on (I'm still doing the Shoot and Learn on the side). From the simple tutorial on how to draw canvas in android, lets explode this area further.

IntroductionBased on the Drawing with Canvas in Android lets put the SurfaceView into a separate class (you should know how to use custom view), create a DrawingPath class which would contain our Path and Paint object, and create a DrawingActivity where our touch events, buttons to change colors are located.

Explanation<com.almondmendoza.drawings.DrawingSurface android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/drawingSurface"/>We start off by using our custom view in our xml, its as simple as creating a class and using it on the layout.

public class DrawingPath { public Path path; public Paint paint;}From Drawing with Canvas in Android we learn to put an ArrayList of Path which have a single color, for us to have different colors on different path, we create a class which would be an List in our DrawThread later on.

private Paint currentPaint;....private void setCurrentPaint(){ currentPaint = new Paint(); currentPaint.setDither(true); currentPaint.setColor(0xFFFFFF00); currentPaint.setStyle(Paint.Style.STROKE); currentPaint.setStrokeJoin(Paint.Join.ROUND); currentPaint.setStrokeCap(Paint.Cap.ROUND); currentPaint.setStrokeWidth(3);}Here we create a Paint that would serve as our current paint, and set the currentPaint at the start of our activity.

public void onClick(View view){ switch (view.getId()){ case R.id.colorRedBtn: currentPaint = new Paint(); currentPaint.setDither(true); currentPaint.setColor(0xFFFF0000);... break; case R.id.colorBlueBtn: currentPaint = new Paint(); currentPaint.setDither(true); currentPaint.setColor(0xFF00FF00);...This is how we change the currentPaint's color, since we use the Paint object, you could use any of its property/methods thus making every Path beautiful :)

public boolean onTouch(View view, MotionEvent motionEvent) { if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){ currentDrawingPath = new DrawingPath(); currentDrawingPath.paint = currentPaint; currentDrawingPath.path = new Path(); .... drawingSurface.addDrawingPath(currentDrawingPath); } return true;}In the previous tutorial, we bind our onTouch on the surfaceView directly, now we bind it in our activity, this way we could control the logic of the touches better (where you would apply your own shared touch library) and you could do things that doesnt harm the SurfaceView/Canvas.

public DrawThread(SurfaceHolder surfaceHolder){ mSurfaceHolder = surfaceHolder; mDrawingPaths = Collections.synchronizedList(new ArrayList());}As stated earlier we would create a List of DrawingPath, but in able to manipulate it while our thread is running we need to make sure that its thread-safe thus we call Collections.synchronizedList(new ArrayList()); (I'm not sure about this since i never used threads in other language besides Javascript's webworker)

public void addDrawingPath (DrawingPath drawingPath){ thread.addDrawingPath(drawingPath); }From our activity we would pass a DrawingPath to our surfaceView which we would then pass it to our thread, we do this so that our thread would not be accessible to the outside world of our DrawingSurface, which i believe is better for we can inject logics that would deal with our SurfaceView before passing it to our thread.

public void addDrawingPath(DrawingPath drawingPath){ mDrawingPaths.add( drawingPath );}From our DrawingSurface to our DrawThread, we pass the a DrawingPath and add it to our list

synchronized(mDrawingPaths) { Iterator i = mDrawingPaths.iterator(); while (i.hasNext()){ final DrawingPath drawingPath = (DrawingPath) i.next(); canvas.drawPath(drawingPath.path, drawingPath.paint); }}Here we use the Iterator class to iterate over our DrawingPath list and draw our Path on the canvas.

ConclusionNow we learn how to better put our codes and make sure it can be scale up (im a webdeveloper, ahha) in the future.