2017-02-20 118 views
0

我正在嘗試在我正在開發的應用程序中編寫半透明橡皮擦畫筆,但發現兩個問題依賴於它的實現方式。希望有一個我可以指出的解決方法。畫布上的半透明橡皮刷

的代碼示例,在單聲道的機器人/ 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),第二種是直接在OnDraw提供的canvas上繪製。如下所示

我的問題:

如果我畫到DrawCanvas,我收到了疊加效應,其中擦除線逐漸變得越來越透明。這是可以理解的,因爲在每個OnDraw循環中,橡皮擦路徑被烘焙到canvasBitmap中。

如果我直接畫canvas提供的OnDraw我得到「black line」的問題,這也有一定意義,因爲它是擦除到沒有。當路徑被繪製到canvasBitmapUp事件中時,一切都看起來很正確,並且有一個很好的半透明橡皮擦線。

理想情況下,有一個不同的解決方案,我不知道「black line」的問題,但我一直無法找到任何東西。我也嘗試着想辦法緩存canvasBitmap,並且在繪製事件正在進行時使用該事件,而不是使用Move事件正在繪製的活動副本。

有沒有人有我可以看看哪些可能會提出解決方案? Java很好,因爲它很容易移植到C#。

非常感謝提前! 奈傑爾

回答

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事件中,它會再次循環,然後清空變量。

不漂亮,但它的作品。

任何更好的想法,非常感謝!