1

I'm trying to create a specific paint program using a transparent surefaceView, and a brush that was made from a custom bitmap. I looked on this website for answers but couldn't find what I need.

Because of the while loop of the run method, the bitmaps that I'm drawing on the screen are flickering non-stop. It appears as the program is drawing the same bitmaps infinitely which is causing this flicker.

I'm thinking about saving every brush stroke until event.getAction()==MotionEvent.ACTION_UP as a separate bitmap. But I'm having trouble doing this.

This is my Code, I'd appreciate any help with fixing this flickering problem!

public class SurfaceMyPaint extends SurfaceView implements Runnable {

    Thread t;
    SurfaceHolder holder;
    Bitmap brush;
    boolean isItOk = false;

    public SurfaceMyPaint(Context context) 
       {
        super(context);
        holder = getHolder();
        initial();
        }
    public SurfaceMyPaint(Context context, AttributeSet attrs, int defStyle) 
          {
        super(context, attrs, defStyle);
        holder = getHolder();
        initial();
        // TODO Auto-generated constructor stub
          }

    public SurfaceMyPaint(Context context, AttributeSet attrs) 
    {
        super(context, attrs);
        holder = getHolder();

        initial();
        // TODO Auto-generated constructor stub
    }

    public void initial() 
    {
        brush= BitmapFactory.decodeResource(getResources(), R.drawable.brush2);       
    }

    public boolean onTouchEvent(MotionEvent event) 
    {
        if(event.getAction()== MotionEvent.ACTION_DOWN)
        {            
            x= event.getX();
            y= event.getY();
        }

        if(event.getAction()== MotionEvent.ACTION_MOVE)
        {
            x = event.getX();
            y= event.getY();
            Canvas c= holder.lockCanvas();
            c.drawBitmap(brush,x- (brush.getWidth() / 2),y- (brush.getWidth() / 2),null);
            holder.unlockCanvasAndPost(c);
        }
       return true;
    }


    public void run()
    {
        while (isItOk == true)
        {
        if (!holder.getSurface().isValid())
             continue;
         }
    }

    public void pause(){
        isItOk = false;
        while (true){
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            break;
        }
        t=null;
    }
    public void resume(){
        isItOk = true;
        t = new Thread(this);
        t.start();
    }
}
Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
SHAI
  • 789
  • 3
  • 10
  • 43

1 Answers1

0

OK, I found a solution and I'll post it here to help others. This is the link that helped me, and this is the sample of code that I needed. (it was hard to find).

public void run() {
  Canvas canvas = null;
  while (_run){
    try{
      canvas = mSurfaceHolder.lockCanvas(null);
      if(mBitmap == null){
        mBitmap =  Bitmap.createBitmap (1, 1, Bitmap.Config.ARGB_8888);;
      }
      final Canvas c = new Canvas (mBitmap);
      c.drawColor(0, PorterDuff.Mode.CLEAR);
      commandManager.executeAll(c);
      canvas.drawBitmap (mBitmap, 0,  0,null);
    } finally {
      mSurfaceHolder.unlockCanvasAndPost(canvas);
    }
  }
}
}
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
SHAI
  • 789
  • 3
  • 10
  • 43
  • It's flickering because the Surface is double-buffered. You need to erase the entire dirty rect and redraw all visible objects every frame, or use an off-screen Bitmap and copy that over every frame. Your answer appears to do both: it uses an off-screen bitmap, which it fully erases every frame. It would be more efficient to do one or the other. – fadden Sep 18 '15 at 16:35