在画布和多个绘画对象上绘图

时间:2015-11-25 19:27:35

标签: java android android-canvas paint blur

我正在尝试创建一个应用程序,用户可以选择模糊图像,也可以选择在屏幕上绘画(用户也可以在一个画布上执行这两种操作)。

我的工作非常有用,但是在模式从模糊变为绘画之后,我在第一次绘制时出现了一个奇怪的问题,反之亦然。

请参阅下图。

油漆模式

垂直绘制的路径是用户选择了绘制模式的时间。正如您所看到的,第一个路径包含来自模糊绘制对象和绘制对象(带红色笔划)的绘制。现在绘制的任何后续路径都可以正常工作。

BLUR MODE

类似地,您可以看到,在绘制两条垂直路径后,用户将模式切换为模糊并在此模式下绘制水平路径。类似于上面第一个路径的这个时间是两个绘制对象的混合,后续路径工作正常。

请参阅下面发布的代码,如果您可以提出可能导致问题的原因,那就太棒了。

enter image description here

ArrayList<DrawCommands> path_color_stroke_list = new ArrayList<DrawCommands>();
ArrayList<DrawCommands> path_color_stroke_list_undone = new ArrayList<DrawCommands>();
ArrayList<BlurCommands> path_blur_list = new ArrayList<BlurCommands>();
ArrayList<BlurCommands> path_blur_list_undone = new ArrayList<BlurCommands>();
ArrayList<EditTextDrawCommands> editTextList = new ArrayList<EditTextDrawCommands>();

private Bitmap mBitmap;
private Paint transparentPaint;
private Paint mPaint;

public DrawingPanel(Context context, String imageStorageDir) {
    super(context);
    appContext = context;
    setFocusable(true);
    setFocusableInTouchMode(true);
    setClickable(true);
    this.setOnTouchListener(this);

    mPath = new Path();
    setDefaultPaintAttributes();

    BitmapFactory.Options bmOptions = new BitmapFactory.Options();
    bmOptions.inSampleSize = 8;

    blurRefImage = BitmapFactory.decodeResource(getResources(), R.drawable.canvas_test, bmOptions);
    canvasBackImage = BitmapFactory.decodeResource(getResources(), R.drawable.canvas_test);


    //stretch this small image to the size of the device so that it will be stretched and will already be blurred
    blurRefImage = Bitmap.createScaledBitmap(blurRefImage, Utilities.getDeviceWidth(), Utilities.getDeviceHeight(), true);
    blurRefImage = BlurBuilder.blurFullImage(appContext, blurRefImage, 20);

    mBitmap = Bitmap.createBitmap(Utilities.getDeviceWidth(), Utilities.getDeviceHeight(), Bitmap.Config.ARGB_8888);

    mCanvas = new Canvas(mBitmap);

}

protected void setDefaultPaintAttributes() {
    mPaint = new Paint();
    mPaint.setColor(Color.RED);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeCap(Paint.Cap.ROUND);
    mPaint.setStrokeWidth(30);

    //mPaint.setColor(0xcc000000);

    transparentPaint = new Paint();
    transparentPaint.setStyle(Paint.Style.STROKE);
    transparentPaint.setStrokeJoin(Paint.Join.ROUND);
    transparentPaint.setStrokeCap(Paint.Cap.ROUND);
    transparentPaint.setStrokeWidth(60);
    transparentPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

}

@Override
protected void onDraw(Canvas canvas) {
    mCanvas.drawBitmap(canvasBackImage, 0, 0, mPaint);

    //Draw Blur
    for (BlurCommands path_blur : path_blur_list) {
        mCanvas.drawPath(path_blur.getPath(), transparentPaint);
    }

    //Draw Paints
    for (DrawCommands path_clr : path_color_stroke_list) {
        mCanvas.drawPath(path_clr.getPath(), mPaint);
    }

    switch (CURRENT_MODE) {
        case MODE_BLUR:
            mCanvas.drawPath(mPath, transparentPaint);
            break;
        case MODE_PAINT:
            mCanvas.drawPath(mPath, mPaint);
            break;
    }

    canvas.drawBitmap(blurRefImage, 0, 0, mPaint);
    canvas.drawBitmap(mBitmap, 0, 0, mPaint);

}

private void touch_start(float x, float y) {
    mPath.reset();
    mPath.moveTo(x, y);
    mX = x;
    mY = y;
    switch (CURRENT_MODE) {
        case MODE_BLUR:
            break;
        case MODE_PAINT:
            break;
        default:
            break;
    }
}

private void touch_move(float x, float y) {
    float dx = Math.abs(x - mX);
    float dy = Math.abs(y - mY);

    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
        switch (CURRENT_MODE) {
            case MODE_BLUR:
            case MODE_PAINT:
                mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
                mX = x;
                mY = y;
                break;
            default:
                break;
        }

    }

}

private void touch_up(MotionEvent event) {
    switch (CURRENT_MODE) {
        case MODE_BLUR:
            mPath.lineTo(mX, mY);
            mPath = new Path();
            path_blur_list.add(new BlurCommands(mPath, blurStrength, transparentPaint.getStrokeWidth()));
            break;
        case MODE_PAINT:
            mPath.lineTo(mX, mY);
            mPath = new Path();
            path_color_stroke_list.add(new DrawCommands(mPath, mPaint.getColor(), mPaint.getStrokeWidth()));
            Log.d(TAG, "Touch up: X: " + mX + " Y: " + mY);
            break;
        default:
            break;
    }
}

2 个答案:

答案 0 :(得分:4)

您可能想要在touch_up中切换清除路径(新路径)的2行的顺序,并添加广告到列表的路径(首先添加,然后清除)

答案 1 :(得分:1)

发生错误是因为mPath对象的创建与之前的绘图模式匹配,因为它是在使用上一个绘图模式的鼠标向上创建的。

将mPath创建移至 touch_start ,将使用当前绘图模式:

private void touch_start(float x, float y) {
    mPath = new Path();
    mPath.moveTo(x, y);
    mX = x;
    mY = y;
    switch (CURRENT_MODE) {
        case MODE_BLUR:
            path_blur_list.add(new BlurCommands(mPath, blurStrength, transparentPaint.getStrokeWidth()));
            break;
        case MODE_PAINT:
            path_color_stroke_list.add(new DrawCommands(mPath, mPaint.getColor(), mPaint.getStrokeWidth()));
            break;
        default:
            break;
    }
}
...
private void touch_up(MotionEvent event) {
    mPath.lineTo(mX, mY);
}