画布上的半透明橡皮擦画笔

时间:2017-02-20 21:27:57

标签: android android-canvas

我正在尝试将半透明橡皮刷写入我正在开发的应用程序中,但发现了两个问题,具体取决于它是如何实现的。希望有一个我可以指出的解决方法。

代码样本是单声道droid / xamarin

所以,通常我有一个设置,它将路径绘制到绘图画布上。我的视图的OnDraw方法绘制了它的基本位图,然后是我的路径。

    // Canvas is set up elsewhere
    canvasBitmap = Bitmap.CreateBitmap(w, h, Bitmap.Config.Argb8888);
    DrawCanvas.SetBitmap(canvasBitmap);


    protected override void OnDraw(Canvas canvas)
    {
        base.OnDraw(canvas);

        // Draw the saved canvas bitmap
        canvas.DrawBitmap(canvasBitmap, 0, 0, canvasPaint);

        // On top of that draw the current path
        canvas.DrawPath(DrawPath, DrawPaint);
    }



    public bool OnTouch(View view, MotionEvent ev)
    {
        float touchX = ev.GetX();
        float touchY = ev.GetY();


        switch (ev.Action)
        {
            case MotionEventActions.Down:

                if (Editable)
                {
                    // I've removed a bunch of code here but it basically
                    // moves the path start to the touch point and sets
                    // up the brush to start erasing. It does set the
                    // porterduff mode to dstOur
                    DrawPaint.SetMaskFilter(null);
                    DrawPaint.SetXfermode( new PorterDuffXfermode(PorterDuff.Mode.DstOut));

                    DrawPath.MoveTo(touchX, touchY);

                } else { return false;  }
                break;

            case MotionEventActions.Move:

                // Just draws a line to the new touch coordinates
                DrawPath.LineTo(touchX, touchY);

                break;
            case MotionEventActions.Up:
            case MotionEventActions.Cancel:

                // saves some data about the path and draws to the drawing canvas.
                DrawCanvas.DrawPath(DrawPath, DrawPaint);

                // Recycle it
                DrawPath.Reset();

                break;

        }
        return true;
    }

因此在绘制橡皮擦线时有两种方法可以绘制橡皮擦线。第一种是绘制绘图画布(写入canvasBitmap),第二种是直接绘制canvas提供的OnDraw

我的问题如下:

如果我画到DrawCanvas,我会得到一个堆叠效果,其中擦除的线逐渐变得越来越透明。这是可以理解的,因为在每个OnDraw循环中,橡皮擦路径被烘焙到canvasBitmap

如果我直接绘制到canvas提供的OnDraw,我会遇到“black line”问题,这也是有意义的,因为它正在删除。当路径被绘制到canvasBitmap事件中的Up时,一切看起来都正确,并且有一条漂亮的半透明橡皮擦线。

理想情况下,有一个不同的解决方案,我不知道“black line”问题,但我找不到任何东西。我也尝试过考虑缓存canvasBitmap的方法,并且在绘制事件正在进行时使用而不是Move事件所吸引的主动副本。

有没有人有什么我可以看看哪些可能暗示解决方案? Java很好,因为它很容易移植到c#。

非常感谢提前! 佰

1 个答案:

答案 0 :(得分:0)

如果没有比我更有经验/聪明才智的人,我会以一种可怕的方式绕过它。当我继续寻找一种更聪明的方法时,它可能对其他人有帮助。

Down事件发生时,我将位图的干净副本抓取到临时变量中。在每个OnDraw事件中,我读取了清理位图,然后在其上绘制擦除路径。

可怕的是,每个OnDraw事件都有一个位图复制方法,以确保不会发生擦除路径加倍。

OnDraw( Canvas canvas )
{
            tempBitmap.Recycle();
            tempBitmap = _drawingBitmap.Copy(_drawingBitmap.GetConfig(), true);

            DrawCanvas.DrawColor(Color.Transparent, PorterDuff.Mode.Clear);
            DrawCanvas.DrawBitmap(tempBitmap, 0, 0, DrawPaint));
            DrawCanvas.DrawPath(DrawPath, DrawPaint);
}

位图回收显然非常关键。在触摸侦听器中的.Up事件中,它再次循环,然后使变量为空。

不漂亮,但确实有效。

任何更好的想法都非常赞赏!