How can I extend the drawing area when it reached the end and there is an issue in clear function when the user clears the screen using clearCanvas()
and gets pressed undo()
button then the paint color
and stroke-width
behavior changed. how can I fix it? And now I want to support pdf file in drawing area also for draw over it.
Below is my custom view code and screenshot:
package co.ctdworld.sketchapp;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
public class DrawingView extends View
{
private Path mDrawPath;
private Paint mBackgroundPaint;
private Paint mDrawPaint;
private Canvas mDrawCanvas;
private Bitmap mCanvasBitmap;
private ArrayList<Path> mPaths = new ArrayList<>();
private ArrayList<Paint> mPaints = new ArrayList<>();
private ArrayList<Path> mUndonePaths = new ArrayList<>();
private ArrayList<Paint> mUndonePaints = new ArrayList<>();
private ArrayList<Path> mLastPaths = new ArrayList<>();
private ArrayList<Paint> mLastPaints = new ArrayList<>();
// Set default values
private int mBackgroundColor = 0xFFFFFFFF;
private int mPaintColor = getContext().getResources().getColor(R.color.colorPrimaryDark);
private int mStrokeWidth = 8;
public DrawingView(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
private void init()
{
mDrawPath = new Path();
mBackgroundPaint = new Paint();
initPaint();
}
private void initPaint()
{
mDrawPaint = new Paint();
mDrawPaint.setColor(mPaintColor);
mDrawPaint.setAntiAlias(true);
mDrawPaint.setStrokeWidth(mStrokeWidth);
mDrawPaint.setStyle(Paint.Style.STROKE);
mDrawPaint.setStrokeJoin(Paint.Join.ROUND);
mDrawPaint.setStrokeCap(Paint.Cap.ROUND);
}
private void drawBackground(Canvas canvas)
{
mBackgroundPaint.setColor(mBackgroundColor);
mBackgroundPaint.setStyle(Paint.Style.FILL);
canvas.drawRect(0, 0, this.getWidth(), this.getHeight(), mBackgroundPaint);
}
private void drawPaths(Canvas canvas)
{
int i = 0;
for (Path p : mPaths)
{
canvas.drawPath(p, mPaints.get(i));
i++;
}
}
@Override
protected void onDraw(Canvas canvas)
{
drawBackground(canvas);
drawPaths(canvas);
canvas.drawPath(mDrawPath, mDrawPaint);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
mCanvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mDrawCanvas = new Canvas(mCanvasBitmap);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
mDrawPath.reset();
mDrawPath.moveTo(touchX, touchY);
//mDrawPath.addCircle(touchX, touchY, mStrokeWidth/10, Path.Direction.CW);
break;
case MotionEvent.ACTION_MOVE:
mDrawPath.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
mDrawPath.lineTo(touchX, touchY);
mPaths.add(mDrawPath);
mPaints.add(mDrawPaint);
mDrawPath = new Path();
initPaint();
break;
default:
return false;
}
invalidate();
return true;
}
public void setPaintColor(int color)
{
mPaintColor = color;
mDrawPaint.setColor(mPaintColor);
}
public void setPaintStrokeWidth(int strokeWidth)
{
mStrokeWidth = strokeWidth;
mDrawPaint.setStrokeWidth(mStrokeWidth);
}
public void setBackgroundColor(int color)
{
mBackgroundColor = color;
mBackgroundPaint.setColor(mBackgroundColor);
invalidate();
}
public Bitmap getBitmap()
{
drawBackground(mDrawCanvas);
drawPaths(mDrawCanvas);
return mCanvasBitmap;
}
public void undo()
{
if (mPaths.size() > 0)
{
mUndonePaths.add(mPaths.remove(mPaths.size() - 1));
mUndonePaints.add(mPaints.remove(mPaints.size() - 1));
invalidate();
}else if (mLastPaths.size() > 0){
for (Path p : mLastPaths){
mPaths.add(p);
}
if (mLastPaints.size() > 0) {
for (Paint p : mLastPaints) {
mPaints.add(p);
}
}
invalidate();
}
}
public void redo()
{
if (mUndonePaths.size() > 0)
{
mPaths.add(mUndonePaths.remove(mUndonePaths.size() - 1));
mPaints.add(mUndonePaints.remove(mUndonePaints.size() - 1));
}
invalidate();
}
public void clearCanvas()
{
if (mPaths.size() > 0) {
for (Path p : mPaths) {
mLastPaths.add(p);
}
if (mPaints.size() > 0){
for (Paint p : mPaints){
mLastPaints.add(p);
}
}
//TODO: there is a bug relate with on touch move
mDrawPath.reset();
mPaths.clear();
invalidate();
}
invalidate();
}
public void erase(boolean isEraseOn){
if (isEraseOn){
setPaintColor(Color.WHITE);
}
}
}
There is a fix for your current code issue:
package co.ctdworld.sketchapp;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
public class DrawingView extends View
{
private Path mDrawPath;
private Paint mBackgroundPaint;
private Paint mDrawPaint;
private Canvas mDrawCanvas;
private Bitmap mCanvasBitmap;
private ArrayList<Path> mPaths = new ArrayList<>();
private ArrayList<Paint> mPaints = new ArrayList<>();
private ArrayList<Path> mUndonePaths = new ArrayList<>();
private ArrayList<Paint> mUndonePaints = new ArrayList<>();
private ArrayList<Path> mLastPaths = new ArrayList<>();
private ArrayList<Paint> mLastPaints = new ArrayList<>();
// Set default values
private int mBackgroundColor = 0xFFFFFFFF;
private int mPaintColor = getContext().getResources().getColor(R.color.colorPrimaryDark);
private int mStrokeWidth = 8;
public DrawingView(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
private void init()
{
mDrawPath = new Path();
mBackgroundPaint = new Paint();
initPaint();
}
private void initPaint()
{
mDrawPaint = new Paint();
mDrawPaint.setColor(mPaintColor);
mDrawPaint.setAntiAlias(true);
mDrawPaint.setStrokeWidth(mStrokeWidth);
mDrawPaint.setStyle(Paint.Style.STROKE);
mDrawPaint.setStrokeJoin(Paint.Join.ROUND);
mDrawPaint.setStrokeCap(Paint.Cap.ROUND);
}
private void drawBackground(Canvas canvas)
{
mBackgroundPaint.setColor(mBackgroundColor);
mBackgroundPaint.setStyle(Paint.Style.FILL);
canvas.drawRect(0, 0, this.getWidth(), this.getHeight(), mBackgroundPaint);
}
private void drawPaths(Canvas canvas)
{
int i = 0;
for (Path p : mPaths)
{
canvas.drawPath(p, mPaints.get(i));
i++;
}
}
@Override
protected void onDraw(Canvas canvas)
{
drawBackground(canvas);
drawPaths(canvas);
canvas.drawPath(mDrawPath, mDrawPaint);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
mCanvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mDrawCanvas = new Canvas(mCanvasBitmap);
}
@Override
public boolean onTouchEvent(MotionEvent event)
{
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
mDrawPath.reset();
mDrawPath.moveTo(touchX, touchY);
mUndonePaths.clear();
//mDrawPath.addCircle(touchX, touchY, mStrokeWidth/10, Path.Direction.CW);
break;
case MotionEvent.ACTION_MOVE:
mDrawPath.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
mDrawPath.lineTo(touchX, touchY);
mPaths.add(mDrawPath);
mPaints.add(mDrawPaint);
mDrawPath = new Path();
initPaint();
break;
default:
return false;
}
invalidate();
return true;
}
public void setPaintColor(int color)
{
mPaintColor = color;
mDrawPaint.setColor(mPaintColor);
}
public void setPaintStrokeWidth(int strokeWidth)
{
mStrokeWidth = strokeWidth;
mDrawPaint.setStrokeWidth(mStrokeWidth);
}
public void setBackgroundColor(int color)
{
mBackgroundColor = color;
mBackgroundPaint.setColor(mBackgroundColor);
invalidate();
}
public Bitmap getBitmap()
{
drawBackground(mDrawCanvas);
drawPaths(mDrawCanvas);
return mCanvasBitmap;
}
public void undo()
{
if (mPaths.size() > 0)
{
mUndonePaths.add(mPaths.remove(mPaths.size() - 1));
mUndonePaints.add(mPaints.remove(mPaints.size() - 1));
invalidate();
}else if (mLastPaths.size() > 0){
for (Path p : mLastPaths){
mPaths.add(p);
}
if (mLastPaints.size() > 0) {
for (Paint p : mLastPaints) {
mPaints.add(p);
}
}
invalidate();
}
}
public void redo()
{
if (mUndonePaths.size() > 0)
{
mPaths.add(mUndonePaths.remove(mUndonePaths.size() - 1));
mPaints.add(mUndonePaints.remove(mUndonePaints.size() - 1));
}
invalidate();
}
public void clearCanvas()
{
//for only last deleted path
mLastPaths.clear();
mLastPaints.clear();
if (mPaths.size() > 0) {
for (Path p : mPaths) {
mLastPaths.add(p);
}
if (mPaints.size() > 0){
for (Paint p : mPaints){
mLastPaints.add(p);
}
}
mPaths.clear();
mPaints.clear();
mUndonePaths.clear();
mUndonePaints.clear();
mDrawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
}
}
}
User contributions licensed under CC BY-SA 3.0