This is the first time I am working with the Canvas class in Android.
What I want is to draw lines in different colors on the canvas. I have an issue I cannot resolve.
I draw the first line in black, after I change the color to red and try to draw a second line in red, and the first line drawn in black color changes to red.
Code I used is:
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
public class DrawView extends View implements OnTouchListener
{
private Canvas m_Canvas;
private Path m_Path;
private Paint m_Paint;
ArrayList<Pair<Path, Paint>> paths = new ArrayList<Pair<Path, Paint>>();
ArrayList<Pair<Path, Paint>> undonePaths = new ArrayList<Pair<Path, Paint>>();
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
// Bitmap canvasBackground;
public DrawView(Context context)
{
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
onCanvasInitialization();
}
public void onCanvasInitialization()
{
m_Paint = new Paint();
m_Paint.setAntiAlias(true);
m_Paint.setDither(true);
m_Paint.setColor(Color.parseColor("#37A1D1"));
m_Paint.setStyle(Paint.Style.STROKE);
m_Paint.setStrokeJoin(Paint.Join.ROUND);
m_Paint.setStrokeCap(Paint.Cap.ROUND);
m_Paint.setStrokeWidth(2);
m_Canvas = new Canvas();
m_Path = new Path();
Paint newPaint = new Paint(m_Paint);
paths.add(new Pair<Path, Paint>(m_Path, newPaint));
// Bitmap canvas = BitmapFactory.decodeResource(getResources(), R.drawable.theme1_img_note).copy(Bitmap.Config.ARGB_8888, true);
// canvasBackground = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888 );
// m_Canvas = new Canvas(canvasBackground);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas)
{
for (Pair<Path, Paint> p : paths)
{
canvas.drawPath(p.first, p.second);
}
}
public boolean onTouch(View arg0, MotionEvent event)
{
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
private void touch_start(float x, float y)
{
m_Path.reset();
m_Path.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y)
{
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
{
m_Path.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
}
}
private void touch_up()
{
m_Path.lineTo(mX, mY);
// commit the path to our offscreen
m_Canvas.drawPath(m_Path, m_Paint);
// kill this so we don't double draw
m_Path = new Path();
Paint newPaint = new Paint(m_Paint); // Clones the mPaint object
paths.add(new Pair<Path, Paint>(m_Path, newPaint));
}
public void onClickPenButton(int penWidth)
{
m_Paint.setStrokeWidth(penWidth);
m_Path = new Path();
Paint newPaint = new Paint(m_Paint); // Clones the mPaint object
paths.add(new Pair<Path, Paint>(m_Path, newPaint));
}
public void onClickPenColorButton(int penColor)
{
m_Paint.setColor(penColor);
Paint newPaint = new Paint(m_Paint); // Clones the mPaint object
paths.add(new Pair<Path, Paint>(m_Path, newPaint));
}
public void onClickUndo ()
{
if (paths.size()>0)
{
undonePaths.add(paths.remove(paths.size()-1));
invalidate();
}
else
{
}
}
public void onClickRedo ()
{
if (undonePaths.size()>0)
{
paths.add(undonePaths.remove(undonePaths.size()-1));
invalidate();
}
else
{
}
}
}
You have only one m_Paint
object, so when onDraw
is called it will draw all paths using the last color you have set.
You can store the color for each path and inside onDraw
you have to set the color before drawing the path
Edit
Here is the outline for a quick solution, night not be the most elegant one:
HashMap
with the path as key and the Color as valueonClickPenColorButton
save the color to an instance say currentColor
touch_start
you can push the path object with the currentColor
into the HashMap
Modify onDraw to get the color for each path. This code is only for illustration so modify it as needed.
protected void onDraw(Canvas canvas)
{
for (Path p : paths)
{
// Assuming your HashMap variable is pathColor
m_Paint.setColor(pathColor.get(p));
canvas.drawPath(p, m_Paint);
}
}