在android中自定义图像视图上撤消绘图

时间:2015-02-02 12:55:42

标签: android android-activity canvas android-canvas android-drawable

我正在处理绘图应用程序,到目前为止我能够在图像上画线,问题是我发现它无法在自定义图像视图中集成撤消操作。

我应用“逐个存储绘制路径,并在onDraw短语上绘制它”的逻辑,但代码中似乎有一些缺失/缺陷。

如果您想了解有关代码的更多详细信息,欢迎提出任何问题。截图是我的应用程序的样子(在图像上绘图)

感谢您的帮助。

主要活动

// 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();
                }
            }
        });

自定义图片视图

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

enter image description here

更新:测试结果

经过测试一段时间后,发现该应用程序运行但所选图像未在自定义图像视图中绘制,如下所示:

如果你有空闲时间,我上传项目(<1 mb), 它是一个小型绘图工具,首先将带有一些图像的文件夹复制到设备中的“HistoryTool”文件夹

路径,例如:

sd card root/ HistoryTool/ folder1 / a.jpg 

,那么你可以在它上面绘制,就是这样,但是现在撤销操作不起作用,需要修复。

https://drive.google.com/file/d/0B9mELZtUJp0LLVh0b1Q0a3VTcG8/view?usp=sharing

非常感谢

enter image description here

1 个答案:

答案 0 :(得分:1)

实际上我认为我找到了问题的根源:每次捕获一个MotionEvent.ACTION_MOVE时都会添加一条新路径,但是触摸传感器非常嘈杂而且你会收到很多这样的事件。您可以考虑编辑在检测到MotionEvent.ACTION_DOWN时添加的现有路径。我会考虑做这样的事情

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;
  }
};

请务必将currentPath声明为自定义View类的私有字段。抱歉,我现在无法测试代码,所以如果您对此代码有疑问,请告诉我,晚上我会给您一个经过测试的代码。

编辑:抱歉,我在ACTION_MOVE处理中添加了额外的moveTo,这将阻止正确的工作代码

相关问题