在 android 中的图像视图 canvas 上绘制透明线

Drawing transparent line on canvas of imageview in android

问题是,我尝试将不透明度更改为 100,这应该是透明的,但是当我尝试画线时,线上出现了一些圆圈。 (参考屏幕截图)如果提供一些示例代码,我们将不胜感激。非常感谢您的帮助。

来自 MainActivity 的代码

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

  pen.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View arg0) {
                    draw_view.setAlpha(100);
                }
            }
        });

以及来自自定义 imageView 的代码

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

以及截图

更新:项目代码

由于通过代码提取很难找出问题所在,我上传了项目(<1 mb)以及使用的库:

如果你有空,欢迎看一看 这是一个小型绘图工具,首先将一个包含一些图像的文件夹复制到您设备

中的文件夹"HistoryTool"

路径,例如:

sd card root/ HistoryTool/ folder1 / a.jpg 

,然后就可以在上面画画了,但是画的透明线上面有圆圈。就这些

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

来自文档 Paint.setAlpha(int)

set the alpha component [0..255] of the paint's color.

表示0是透明的,255是完全不透明的。 100 你只是设置为中间值。

我已经使用 On-draw 和 Path 完成了任务

        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();
                        holderList.add(new Holder(color, width, alpha));
                        holderList.get(holderList.size() - 1).path.moveTo(downx, downy);
                        break;
                    case MotionEvent.ACTION_MOVE:
                        upx = getPointerCoords(event)[0];// event.getX();
                        upy = getPointerCoords(event)[1];// event.getY();
                        holderList.get(holderList.size() - 1).path.lineTo(upx, upy);
                        invalidate();
                        downx = upx;
                        downy = upy;
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                    case MotionEvent.ACTION_CANCEL:
                        break;
                    default:
                        break;
                }
            }
            return true;
        }
    };

    setOnTouchListener(drawListener);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    if (img != null) {
        tmp_canvas.drawBitmap(img, 0, 0, null);
    }
    for (Holder holder : holderList) {
        tmp_canvas.drawPath(holder.path, holder.paint);
    }
}

//draw view start
public void setNewImage(Bitmap alteredBitmap, Bitmap bmp) {
    tmp_canvas = new Canvas(alteredBitmap);
    img = bmp;
    tmp_canvas.drawBitmap(bmp, 0, 0, null);
    setImageBitmap(alteredBitmap);
}

所以,你的问题是圈圈就行了。这来自于单独绘制的线链的每个新段,以及与先前绘制的链段重叠的每个端点。您想在调用之前绘制直线路径 stroke(); 这将绘制整个线段链一次而不是单独绘制并防止那些圆形重叠。

你可以做的是这样的:制作一个线链 class 一次绘制所有线:

/* Feed the line chain an array of points to draw when you construct it. */
/* points_=[{"x":0,"y":0},{"x":10,"y":10}]; */
function LineChain(points_){
    this.points=points_;
}

LineChain.prototype={
    constructor:LineChain,
    /* Draws this line chain to the specified context. */
    drawTo:function(context_){
        /* Get the first point in the chain. */
        var point=this.points[0];
        /* Start the path by moving to the first position on the chain. */
        context_.beginPath();
        context_.moveTo(point.x,point.y);
        /* Loop through the remaining points in the chain and draw the rest of the path. */
        for (var index=1;index<this.points.length-1;index++){
            point=this.points[index];
            context_.lineTo(point.x,point.y);
        }
    }
}

现在,当您真正想要将链条绘制到 canvas 时,只需执行以下操作:

/* Define a line chain. */
var line_chain=new LineChain([{"x":0,"y":0},{"x":10,"y":20},{"x":30,"y":40}]);

/* Wherever you're drawing at... */
context.strokeStyle="rgba(255,0,0,0.5)";
context.lineWidth=20;
line_chain.drawTo(context);
context.stroke();

基本上,如何实现此技术并不重要,您唯一需要做的就是确保在调用 stroke 函数之前绘制了整个路径。

请参考混合模式,这将帮助您解决这个问题。 期望:如果我们在其自身上绘制相同的笔画,它不应该过度绘制并降低透明度。

参考以下链接。

https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/BlendMode

https://medium.com/mobile-app-development-publication/practical-image-porterduff-mode-usage-in-android-3b4b5d2e8f5f