Android application cancellation method (singletouch) does not work properly

I am working on a graphical application, but am facing some cancellation issues. Encoding is as follows:

public class DoodleView extends View { Context context_new; private static final float TOUCH_TOLERANCE = 5; private Bitmap bitmap; // drawing area for display or saving private Canvas bitmapCanvas; // used to draw on bitmap private Paint paintScreen; // use to draw bitmap onto screen private Paint paintLine; // used to draw lines onto bitmap private Path mPath; private ArrayList<Path> paths = new ArrayList<Path>(); private ArrayList<Path> undonePaths = new ArrayList<Path>(); private float mX, mY; // DoodleView constructor initializes the DoodleView public DoodleView(Context context, AttributeSet attrs) { super(context, attrs); // pass context to View constructor this.context_new=context; paintScreen = new Paint(); // used to display bitmap onto screen // set the initial display settings for the painted line paintLine = new Paint(); paintLine.setAntiAlias(true); // smooth edges of drawn line paintLine.setColor(Color.BLACK); // default color is black paintLine.setStyle(Paint.Style.STROKE); // solid line mPath = new Path(); paths.add(mPath); } // end DoodleView constructor 

OnSizeChanged:

  @Override public void onSizeChanged(int w, int h, int oldW, int oldH) { super.onSizeChanged(w, h, oldW, oldH); DoodlzViewWidth = w; DoodlzViewHeight = h; bitmap = Bitmap.createBitmap(getWidth(), DoodlzViewHeight, Bitmap.Config.ARGB_8888); bitmapCanvas = new Canvas(bitmap); bitmap.eraseColor(Color.WHITE); // erase the BitMap with white } 

onDraw:

  @Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(bitmap, 0, 0, paintScreen); // for each path currently being drawn for (Path p : paths){canvas.drawPath(p, paintLine);} } 

onTouchEvent:

  @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: touchStarted(x, y); invalidate(); break; case MotionEvent.ACTION_MOVE: touchMoved(x, y); invalidate(); break; case MotionEvent.ACTION_UP: touchEnded(); invalidate(); break; } return true; } 

touchStarted:

  private void touchStarted(float x, float y) { mPath.reset(); mPath.moveTo(x, y); mX = x; mY = y; } 

touchMoved:

  private void touchMoved(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; } } 

touchEnded:

  private void touchEnded() { mPath.lineTo(mX, mY); bitmapCanvas.drawPath(mPath, paintLine); mPath = new Path(); paths.add(mPath); Toast.makeText(getContext(), "touchEnded" + paths.size(), Toast.LENGTH_SHORT).show(); } 

Undo:

 public void onClickUndo() { Toast.makeText(getContext(), "before undo button pressed " + paths.size(), Toast.LENGTH_SHORT).show(); if (paths.size()>0) { undonePaths.add(paths.remove(paths.size()-1)); Toast.makeText(getContext(), "after undo button pressed " + paths.size(), Toast.LENGTH_SHORT).show(); Log.i("UNDOING", "PREPARE INVALIDATE"); invalidate(); Log.i("UNDOING", "FINISH INVALIDATE"); } else Toast.makeText(getContext(), "nothing to undo" + paths.size(), Toast.LENGTH_SHORT).show(); } 

Question:

The above is from other examples found on the Internet. I don’t know why I need to set path.reset () when implementing touchStarted ?

Q1. When I press the cancel button, it correctly shows the cancel button toast undo and reports that path.size() is 0, and therefore, the drawn line is not deleted immediately. I really don't know why this is 0 ?? Isn't it added to the array of paths? How can I change the code?

** code changed after the adoption of the advice of the developer android-developer! Thank you !! Now it correctly shows path.size (). Sorry for the stupid missed! * But the previous dash cannot be deleted? = (

Q2. Although the application works correctly when the finger moves on the screen and immediately shows a line. When I press the cancel button, in addition to the fact that the previous line is not deleted, the lines continue to stretch to the screen after pressing the button, the button will not be displayed until the finger is lifted.

answer to Q2: moving below 2 lines from touchEnded() to touchStarted()

 mPath = new Path(); paths.add(mPath); 

.

  private void touchStarted(float x, float y) { mPath.reset(); mPath = new Path(); paths.add(mPath); mPath.moveTo(x, y); mX = x; mY = y; } private void touchEnded() { mPath.lineTo(mX, mY); bitmapCanvas.drawPath(mPath, paintLine);// commit the path to our offscreen Toast.makeText(getContext(), "touchEnded" + paths.size(), Toast.LENGTH_SHORT).show(); } 

Thanks!!!

+4
source share
1 answer

updated and working:

  • removed Paint paintScreen;
  • In onDraw do not put canvas.drawBitmap(bitmap, 0, 0, paintScreen); or canvas.drawBitmap(bitmap, 0, 0, paintLine);

     private Bitmap bitmap; // drawing area for display or saving private Canvas bitmapCanvas; // used to draw on bitmap private Paint paintLine; // used to draw lines onto bitmap private Path mPath; private ArrayList<Path> paths = new ArrayList<Path>(); private ArrayList<Path> undonePaths = new ArrayList<Path>(); private float mX, mY; private static final float TOUCH_TOLERANCE = 4; // DoodleView constructor initializes the DoodleView public DoodleView(Context context, AttributeSet attrs) { super(context, attrs); // pass context to View constructor this.context_new=context; setFocusable(true); setFocusableInTouchMode(true); // set the initial display settings for the painted line paintLine = new Paint(); paintLine.setAntiAlias(true); // smooth edges of drawn line paintLine.setDither(true); paintLine.setColor(Color.BLACK); // default color is black paintLine.setStyle(Paint.Style.STROKE); // solid line paintLine.setStrokeJoin(Paint.Join.ROUND); paintLine.setStrokeWidth(5); // set the default line width paintLine.setStrokeCap(Paint.Cap.ROUND); // rounded line ends bitmapCanvas = new Canvas(); mPath = new Path(); } // end DoodleView constructor // Method onSizeChanged creates BitMap and Canvas after app displays @Override public void onSizeChanged(int w, int h, int oldW, int oldH) { super.onSizeChanged(w, h, oldW, oldH); DoodlzViewWidth = w; DoodlzViewHeight = h; } @Override protected void onDraw(Canvas canvas) { for (Path p : paths){canvas.drawPath(p, paintLine);} canvas.drawPath(mPath, paintLine); Log.i("OnDRAWING", "REACH ON DRAW"); } 

    // START TOUCH: handle the touch event @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; } private void touch_start(float x, float y) { undonePaths.clear(); 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); bitmapCanvas.drawPath(mPath, paintLine);// commit the path to our offscreen paths.add(mPath); mPath = new Path(); } public void onClickUndo() { if (paths.size()>0) { undonePaths.add(paths.remove(paths.size()-1)); invalidate(); } else Toast.makeText(getContext(), "nothing more to undo", Toast.LENGTH_SHORT).show(); } 
+4
source

All Articles