Setting the opacity of drawing canvas in android

2019-08-27 04:24发布

问题:

I am working on a function that drawing some transparent line on the canvas, the problem is , there is some "ball shape" on the line as the screenshot show.

Here is my code:

canvas = new Canvas(alteredBitmap);
        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);
        matrix_draw = new Matrix();
        canvas.drawBitmap(bmp, matrix_draw, paint);
        setImageBitmap(alteredBitmap);

press the button to set alpha

   public void setAlpha(int alpha) {
        this.alpha = alpha;
        paint.setAlpha(alpha);
    }

And the listener

    drawListener = new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                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);
                    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);
//                  invalidate();
                    break;
                case MotionEvent.ACTION_CANCEL:
                    break;
                default:
                    break;
                }
                return true;
            }
        };

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

Thanks a lot for helping

回答1:

The ball shapes are where each line segment overlaps the previous one. You can fix this by using a second image overlaid on top of the image that you are editing.

Initialize the overlay image to completely transparent and make it the same size as the image you are editing.

ImageView overlayImageView = findViewById(R.id.overlay);
Bitmap overlayBitmap = Bitmap.createBitmap(imageWidth, imageHeight, Bitmap.Config.ARGB_8888);
overlayBitmap.erase(0x00000000); // transparent
overlayImageView.setImageBitmap(overlayBitmap);

Inside setAlpha() set the alpha of the overlay image to the alpha value.

overlayImageView.setImageAlpha((float)alpha / 255.0f);

When the user is drawing a line, in the case MotionEvent.ACTION_MOVE block, draw the line onto the overlay image instead, but at full opacity. Because all line segments are drawn at full opacity, there won't be any ball shapes where they overlap, but the line will still appear transparent because of the alpha value applied to the overlay image.

In case MotionEvent.ACTION_UP, transfer the line onto the image by drawing the overlay image onto the target image using canvas draw calls, using the alpha value set in setAlpha(), and then clear the overlay image to transparent.