how to stop or pause the drawing on canvas - java

I'm making face editing app. I want to put a drawing on a face with freehand. I want to be able to stop and pause the drawing on canvas. Here is my code:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(testbmp, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
canvas.drawPath(circlePath, circlePaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mPath.reset();
mPath.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) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
circlePath.reset();
circlePath.addCircle(mX, mY, 30, Path.Direction.CW);
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
circlePath.reset();
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath.reset();
}
#Override
public boolean onTouchEvent(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;
}
public void onClickEraser() {
boolean isEraserOn = true;
if (isEraserOn)
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
else
mPaint.setXfermode(null);
}

You can stop the onDraw execution. Will execute all the methods inside it.
Your app or your view could implement some mechanism to manage a drawing queue and the onDraw methods will draw from the beginning to the position you decided but this is not the natural way of work the method.

Related

how to make it drag with 2 fingers?

I am able to pinch zoom in/out (though its not perfect yet) i want to use 2 fingers to drag since single drag is for drawing.
is this where the ACTION_POINTER_DOWN is required?
please help me how i can have the paint app drag with 2 fingers?
Below is the code
Thank you!
public class paintView extends View {
private static final int INVALID_POINTER_ID = -1;
private float mPosX;
private float mPosY;
private int mActivePointerId = INVALID_POINTER_ID;
private final ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
Paint paint;
Path path;
public paintView(Context context) {
super(context, null, 0);
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
paint = new Paint();
path = new Path();
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(8f);
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
// Let the ScaleGestureDetector inspect all events.
mScaleDetector.onTouchEvent(ev);
final int action = ev.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
final float x = ev.getX();
final float y = ev.getY();
path.moveTo(x,y);
return true;
}
case MotionEvent.ACTION_MOVE: {
float x = ev.getX();
float y = ev.getY();
path.lineTo(x,y);
break;
}
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
mActivePointerId = INVALID_POINTER_ID;
break;
}
}
invalidate();
return true;
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
// for moving around
// 2 finger drag 할때 필요할듯
canvas.translate(mPosX, mPosY);
// for zoom
canvas.scale(mScaleFactor, mScaleFactor);
//mImage.draw(canvas);
canvas.drawPath(path, paint);
//canvas.restore();
}
// zoom in gesture
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
final float scale = detector.getScaleFactor();
mScaleFactor = Math.max(.5f, Math.min(mScaleFactor * scale, 3.0f));
if (mScaleFactor < 5f) {
// 1 Grabbing
final float centerX = detector.getFocusX();
final float centerY = detector.getFocusY();
// 2 Calculating difference
float diffX = centerX - mPosX;
float diffY = centerY - mPosY;
// 3 Scaling difference
diffX = diffX * scale - diffX;
diffY = diffY * scale - diffY;
// 4 Updating image origin
mPosX -= diffX;
mPosY -= diffY;
}
invalidate();
return true;
}
}
}

Detect if the user has painted the whole screen

I'm letting the user to do painting in my app.The app will show some options on the screen once the whole screen is painted. And I want to check if the user has painted the whole screen.
Is there a way to detect if the user has painted the whole screen? Like an event triggered after the whole screen is painted.
Following is my code for painting:
public class DrawingView extends View {
public int width;
public int height;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
Context context;
private Paint circlePaint;
private Path circlePath;
Stack mXStack;
Stack mYStack;
public DrawingView(Context c) {
super(c);
context = c;
mPath = new Path();
mXStack = new Stack();
mYStack = new Stack();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
circlePaint = new Paint();
circlePath = new Path();
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.BLUE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(50f);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
canvas.drawPath(circlePath, circlePaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mPath.reset();
mPath.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) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
circlePath.reset();
circlePath.addCircle(mX, mY, 30, Path.Direction.CW);
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
circlePath.reset();
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath.reset();
}
#Override
public boolean onTouchEvent(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;
}
}

How to find drawed with paint line's length in Android Java?

Heres my code to drawing with fingers paint line and draw circle. I want to know how to find line's length and want to draw circle with radius line's length.
How can I do this?
And where to put this line?
circlePath.addCircle(mX, mY, "line's length", Path.Direction.CW);
public class MainActivity extends Activity {
/** Called when the activity is first created. */
Paint mPaint;
float Mx1,My1;
float x,y;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.main);
MyView view1 =new MyView(this);
view1.setBackgroundResource(R.color.colorPrimary);
setContentView(view1);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(10);
}
public class MyView extends View {
private static final float MINP = 0.25f;
private static final float MAXP = 0.75f;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
private Paint circlePaint;
private Path circlePath;
public MyView(Context c) {
super(c);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
circlePaint = new Paint();
circlePath = new Path();
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.BLUE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(8f);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
//canvas.drawLine(mX, mY, Mx1, My1, mPaint);
//canvas.drawLine(mX, mY, x, y, mPaint);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
canvas.drawPath(circlePath, circlePaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mPath.reset();
mPath.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) {
//mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
}
//circlePath.reset();
//circlePath.addCircle(mX, mY, Math.abs(mX - mY), Path.Direction.CW);
}
private void touch_up() {
mPath.lineTo(mX, mY);
//circlePath.reset();
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath.reset();
}
#Override
public boolean onTouchEvent(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);
circlePath.addCircle(mX, mY, x, Path.Direction.CW);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
//Mx1=(int) event.getX();
//My1= (int) event.getY();
invalidate();
break;
}
return true;
}
}
}
I solved.
float first_x, first_y, last_x, last_y, line_lenght;
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
first_x = x;
first_y = y;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
last_x = x;
last_y = y;
line_lenght = (float) Math.pow(Math.abs(first_x-last_x),2) + (float) Math.pow(Math.abs(first_y-last_y),2);
line_lenght = (float) Math.sqrt(line_lenght);
circlePath.reset();
circlePath.addCircle(mX, mY, line_lenght, Path.Direction.CW);
invalidate();
break;
case MotionEvent.ACTION_UP:
last_x = x;
last_y = y;
line_lenght = (float) Math.pow(Math.abs(first_x-last_x),2) + (float) Math.pow(Math.abs(first_y-last_y),2);
line_lenght = (float) Math.sqrt(line_lenght);
circlePath.reset();
circlePath.addCircle(mX, mY, line_lenght, Path.Direction.CW);
touch_up();
//Mx1=(int) event.getX();
//My1= (int) event.getY();
invalidate();
break;
}
return true;
}

fill path after completion android

I want my app to fill the shape automatically after completion. I have autocompleted the shapes and after completion I want them to be filled automatically. The code is posted below. I have used mPath.setFillType in onDraw but that doesnot work.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(mBitmap!=null){
canvas.drawBitmap(drawableBitmap, 0, 0, mBitmapPaint);
mPath.setFillType(Path.FillType.EVEN_ODD);
canvas.drawPath( mPath, mPaint);
canvas.drawPath( circlePath, circlePaint);}
else{}
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
Point point1=new Point();
point1.x= (int) (x);
point1.y = (int) (y);
if(point1!=null)
{
points.add(point1);
}
else
{
System.out.println("POINT IS NULLlllllllllllllllllllllllllll");
}
mPath.reset();
mPath.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) {
mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
circlePath.reset();
circlePath.addCircle(mX, mY, 30, Path.Direction.CW);
}
}
private void touch_up(float x,float y) {
Point point=new Point();
point.x= (int) (x);
point.y = (int) (y);
points.add(point);
mPath.lineTo(mX, mY);
mPath.lineTo(points.get(0).x, points.get(0).y);
circlePath.reset();
// commit the path to our offscreen
if(mCanvas!=null)
mCanvas.drawPath(mPath, mPaint);
points.clear();
mPath.reset();
}
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
float x = arg1.getX();
float y = arg1.getY();
switch (arg1.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
System.out.println("TOUCH MOVEEEEE");
touch_move(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up(x,y);
invalidate();
break;
}
return true;
}

How to exit from drawing view?

In my app, I have extended the class to view. After finishing the draw(Handout from touch), if I will perform touch event, It should not be invoke on the extended view class. It will perform touch event function of Main Activity.
Code :
public class DrawOnImage extends View {
public static Bitmap DrawBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint DrawBitmapPaint;
private Paint mPaint;
#SuppressWarnings("deprecation")
public DrawOnImage(Context c) {
super(c);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(getResources().getColor(android.R.color.holo_green_dark));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(20);
mPath = new Path();
DrawBitmapPaint = new Paint(Paint.DITHER_FLAG);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
DrawBitmap = Bitmap.createBitmap(w, h,
Bitmap.Config.ARGB_4444);
mCanvas = new Canvas(DrawBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
setDrawingCacheEnabled(true);
canvas.drawBitmap(DrawBitmap, 0, 0, DrawBitmapPaint);
canvas.drawPath(mPath, mPaint);
canvas.drawRect(mY, 0, mY, 0, DrawBitmapPaint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mPath.reset();
mPath.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) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
mCanvas.drawPath(mPath, mPaint);
mPath.reset();
}
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
if(DrawBitmap == null) {
setVisibility(INVISIBLE);
}else {
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;
}
}
ParameterGetSet.drawingBitmap = DrawBitmap;
return true;
}
}

Categories

Resources