代码之家  ›  专栏  ›  技术社区  ›  user782104

在android中撤消自定义图像视图上的绘图[已关闭]

  •  1
  • user782104  · 技术社区  · 11 年前

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

    我应用了“逐个存储绘制路径,并在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 回复  |  直到 11 年前
        1
  •  1
  •   Chaosit    11 年前

    事实上,我认为我已经找到了问题的根源:每次捕捉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,这将阻止正确的工作代码

    推荐文章