Issue
I was working on the drawing application, so far I am able to draw line on the image, the problem is I find it can not integrate the undo operation in the custom image view.
I apply the logic of " store the draw path one by one, and draw it on the onDraw phrase", but there seems some missing/ flaws in the code.
Welcome to ask for any question if you would like to know more detail about the code. The screenshot is what my app look like (drawing on the image)
Thanks for helping.
In the Main Activity:
// set image
bitmap = downScale(view.getTag().toString(),1280,1024);
altered_bitmap = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(), bitmap.getConfig());
draw_view.setNewImage(altered_bitmap,bitmap);
undo.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0) {
if (pencil.getVisibility() == View.VISIBLE || pen.getVisibility() == View.VISIBLE) {
draw_view.onClickUndo();
}
}
});
And in the custom image view:
private ArrayList<Path> paths = new ArrayList<Path>();
private Path mPath;
public ScaleImageView(Context context) {
super(context);
sharedConstructing(context);
}
public void sharedConstructing(Context context) {
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
matrix = new Matrix();
m = new float[9];
setImageMatrix(matrix);
setScaleType(ScaleType.MATRIX);
paint = new Paint();
paint.setAntiAlias(true);
paint.setStrokeWidth(width);
paint.setColor(color);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setAlpha(alpha);
drawListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (getDrawable() != null) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
downx = getPointerCoords(event)[0];// event.getX();
downy = getPointerCoords(event)[1];// event.getY();
break;
case MotionEvent.ACTION_MOVE:
upx = getPointerCoords(event)[0];// event.getX();
upy = getPointerCoords(event)[1];// event.getY();
canvas.drawLine(downx, downy, upx, upy, paint);
mPath = new Path();
paths.add(mPath);
invalidate();
downx = upx;
downy = upy;
break;
case MotionEvent.ACTION_UP:
upx = getPointerCoords(event)[0];// event.getX();
upy = getPointerCoords(event)[1];// event.getY();
canvas.drawLine(downx, downy, upx, upy, paint);
mPath = new Path();
paths.add(mPath);
invalidate();
break;
case MotionEvent.ACTION_CANCEL:
break;
default:
break;
}
}
return true;
}
};
setOnTouchListener(drawListener);
}
//draw view start
public void setNewImage(Bitmap alteredBitmap, Bitmap bmp) {
canvas = new Canvas(alteredBitmap);
matrix_draw = new Matrix();
canvas.drawBitmap(bmp, matrix_draw, paint);
setImageBitmap(alteredBitmap);
mPath = new Path();
paths.add(mPath);
}
public void setBrushColor(int color) {
this.color = color;
paint.setColor(color);
paint.setAlpha(alpha);
}
public void setAlpha(int alpha) {
this.alpha = alpha;
paint.setAlpha(alpha);
}
public void setWidth(float width) {
this.width = width;
paint.setStrokeWidth(width);
}
final float[] getPointerCoords(MotionEvent e) {
final int index = e.getActionIndex();
final float[] coords = new float[] { e.getX(index), e.getY(index) };
Matrix matrix = new Matrix();
getImageMatrix().invert(matrix);
matrix.postTranslate(getScrollX(), getScrollY());
matrix.mapPoints(coords);
return coords;
}
public void setIsScale() {
isScale = !isScale;
setOnTouchListener(isScale ? zoomListener : drawListener);
}
@Override
protected void onDraw(Canvas canvas) {
for (Path p : paths){
canvas.drawPath(p, paint_line);
}
}
public void onClickUndo () {
if (paths.size()>0){
paths.remove(paths.size()-1);
invalidate();
}
}
//draw view end
Update: Test result
After tested a while, found that the app runs but selected image is not draw in the custom image view like this:
if you have some spare time , I have upload the project (<1 mb), it is a small drawing tool , first copy a folder with some images to the folder "HistoryTool" in your device
The path , for example, like:
sd card root/ HistoryTool/ folder1 / a.jpg
, then you can draw on it, thats all, but right now the undo operation is not functioning and need to fix.
https://drive.google.com/file/d/0B9mELZtUJp0LLVh0b1Q0a3VTcG8/view?usp=sharing
Thanks a lot
Solution
Actually I think I have found the root of your problem: you add a new path each time you catch a MotionEvent.ACTION_MOVE, but touch sensor is relly noisy and you get lots of those events. You migh consider editing the existing path which you add whenever you detect MotionEvent.ACTION_DOWN. I would consider doing something like this
Path currentPath = null;
drawListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (getDrawable() != null) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
downx = getPointerCoords(event)[0];// event.getX();
downy = getPointerCoords(event)[1];// event.getY();
currentPath = new Path();
currentPath.moveTo(downx, downy);
paths.add(currentPath);
break;
case MotionEvent.ACTION_MOVE:
upx = getPointerCoords(event)[0];// event.getX();
upy = getPointerCoords(event)[1];// event.getY();
currentPath.lineTo(upx, upy);
invalidate();
break;
case MotionEvent.ACTION_UP:
upx = getPointerCoords(event)[0];// event.getX();
upy = getPointerCoords(event)[1];// event.getY();
currentPath.lineTo(upx, upy);
invalidate();
currentPath = null;
break;
case MotionEvent.ACTION_CANCEL:
currentPath = null;
break;
default:
break;
}
}
return true;
}
};
Just be sure to declare currentPath as a private field of your custom View class. Sorry I can't test the code right now, so if you have some problems with this code, please tell me and in the evening I will give you a tested code.
EDIT: Sorry I have added extra moveTo in ACTION_MOVE processing, which will prevent the correct work code
Answered By - Chaosit
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.