Click here to Skip to main content
15,890,512 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I am trying to implement an application to get an image from the device and add it to the canvas then start drawing on it using brush and eraser (like snapchat idea) I used Drawing app as a base

http://code.tutsplus.com/series/create-a-drawing-app-on-android--cms-704

My problem for now is that when I draw on the bitmap it start drawing but when I finished and touch up the drawing disappear.

this is a video for the problem

https://vid.me/rgnF (try to mute the sound there is some noise :) )

‏any help would be appreciated. Thank you

Java
public class DrawingView extends View {



    //drawing path
    private Path drawPath;
    //drawing and canvas paint
    private Paint drawPaint, canvasPaint;
    //initial color
    private int paintColor = 0xFF660000;
    //canvas
    private Canvas drawCanvas;
    //canvas bitmap
    public Bitmap canvasBitmap;
    //brush sizes
    private float brushSize, lastBrushSize;
    //erase flag
    private boolean erase=false;

    public DrawingView(Context context, AttributeSet attrs){
    super(context, attrs);
    setupDrawing();
}

    //setup drawing
private void setupDrawing(){

    //prepare for drawing and setup paint stroke properties
    brushSize = getResources().getInteger(R.integer.medium_size);
    lastBrushSize = brushSize;
    drawPath = new Path();
    drawPaint = new Paint();
    drawPaint.setColor(paintColor);
    drawPaint.setAntiAlias(true);
    drawPaint.setStrokeWidth(brushSize);
    drawPaint.setStyle(Paint.Style.STROKE);
    drawPaint.setStrokeJoin(Paint.Join.ROUND);
    drawPaint.setStrokeCap(Paint.Cap.ROUND);
    canvasPaint = new Paint(Paint.DITHER_FLAG);
}

//size assigned to view
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        drawCanvas = new Canvas(canvasBitmap);


}

//draw the view - will be called after touch event
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);



    canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
    canvas.drawPath(drawPath, drawPaint);

}

@Override
public boolean onTouchEvent(MotionEvent event) {
    float touchX = event.getX();
    float touchY = event.getY();
    //respond to down, move and up events
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            drawPath.moveTo(touchX, touchY);
            break;
        case MotionEvent.ACTION_MOVE:
            drawPath.lineTo(touchX, touchY);
            break;
        case MotionEvent.ACTION_UP:
            drawPath.lineTo(touchX, touchY);
            drawCanvas.drawPath(drawPath, drawPaint);
        drawPath.reset();

            break;
        default:
            return false;
    }
    //redraw
    invalidate();
    return true;

}

//update color
public void setColor(String newColor){
    invalidate();
    paintColor = Color.parseColor(newColor);
    drawPaint.setColor(paintColor);
}

//set brush size
public void setBrushSize(float newSize){
    float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
            newSize, getResources().getDisplayMetrics());
    brushSize=pixelAmount;
    drawPaint.setStrokeWidth(brushSize);
}

//get and set last brush size
public void setLastBrushSize(float lastSize){
    lastBrushSize=lastSize;
}
public float getLastBrushSize(){
    return lastBrushSize;
}

//set erase true or false
public void setErase(boolean isErase){
    erase=isErase;
    if(erase) drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    else drawPaint.setXfermode(null);
}

//start new drawing
public void startNew(){
    drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
    invalidate();
}
}


Java
public class MainActivity extends Activity implements OnClickListener {

//custom drawing view
private DrawingView drawView;
//buttons
private ImageButton currPaint, drawBtn, eraseBtn, newBtn, saveBtn;
//sizes
private float smallBrush, mediumBrush, largeBrush;
Button mBtnPick;
int mWidth;
int mHeight;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mWidth = mHeight = 0;
    //get drawing view
    drawView = (DrawingView)findViewById(R.id.drawing);

    //get the palette and first color button
    LinearLayout paintLayout = (LinearLayout)findViewById(R.id.paint_colors);
    currPaint = (ImageButton)paintLayout.getChildAt(0);
    currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));

    //sizes from dimensions
    smallBrush = getResources().getInteger(R.integer.small_size);
    mediumBrush = getResources().getInteger(R.integer.medium_size);
    largeBrush = getResources().getInteger(R.integer.large_size);

    //draw button
    drawBtn = (ImageButton)findViewById(R.id.draw_btn);
    drawBtn.setOnClickListener(this);

    //set initial size
    drawView.setBrushSize(mediumBrush);

    //erase button
    eraseBtn = (ImageButton)findViewById(R.id.erase_btn);
    eraseBtn.setOnClickListener(this);

    //new button
    newBtn = (ImageButton)findViewById(R.id.new_btn);
    newBtn.setOnClickListener(this);

    //save button
    saveBtn = (ImageButton)findViewById(R.id.save_btn);
    saveBtn.setOnClickListener(this);
    // Getting reference to Button "Pick an Image"
    mBtnPick = (Button) findViewById(R.id.button);

    // Setting OnClickListener for the button
    mBtnPick.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            Intent i = new Intent();
            i.setType("image/*");
            i.setAction(Intent.ACTION_GET_CONTENT);

            Intent customChooserIntent = Intent.createChooser(i, "Pick an image");
            startActivityForResult(customChooserIntent, 10);
        }
    });

    if(savedInstanceState!=null){
        mWidth = savedInstanceState.getInt("width");
        mHeight = savedInstanceState.getInt("height");
        Bitmap bitmap = savedInstanceState.getParcelable("bitmap");
        if(bitmap!=null){
            drawView.canvasBitmap=bitmap;
        }
    }
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

//user clicked paint
public void paintClicked(View view){
    //use chosen color

    //set erase false
    drawView.setErase(false);
    drawView.setBrushSize(drawView.getLastBrushSize());

    if(view!=currPaint){
        ImageButton imgView = (ImageButton)view;
        String color = view.getTag().toString();
        drawView.setColor(color);
        //update ui
        imgView.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
        currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint));
        currPaint=(ImageButton)view;
    }
}

@Override
public void onClick(View view){

    if(view.getId()==R.id.draw_btn){
        //draw button clicked
        final Dialog brushDialog = new Dialog(this);
        brushDialog.setTitle("Brush size:");
        brushDialog.setContentView(R.layout.brush_chooser);
        //listen for clicks on size buttons
        ImageButton smallBtn = (ImageButton)brushDialog.findViewById(R.id.small_brush);
        smallBtn.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                drawView.setErase(false);
                drawView.setBrushSize(smallBrush);
                drawView.setLastBrushSize(smallBrush);
                brushDialog.dismiss();
            }
        });
        ImageButton mediumBtn = (ImageButton)brushDialog.findViewById(R.id.medium_brush);
        mediumBtn.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                drawView.setErase(false);
                drawView.setBrushSize(mediumBrush);
                drawView.setLastBrushSize(mediumBrush);
                brushDialog.dismiss();
            }
        });
        ImageButton largeBtn = (ImageButton)brushDialog.findViewById(R.id.large_brush);
        largeBtn.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                drawView.setErase(false);
                drawView.setBrushSize(largeBrush);
                drawView.setLastBrushSize(largeBrush);
                brushDialog.dismiss();
            }
        });
        //show and wait for user interaction
        brushDialog.show();
    }
    else if(view.getId()==R.id.erase_btn){
        //switch to erase - choose size
        final Dialog brushDialog = new Dialog(this);
        brushDialog.setTitle("Eraser size:");
        brushDialog.setContentView(R.layout.brush_chooser);
        //size buttons
        ImageButton smallBtn = (ImageButton)brushDialog.findViewById(R.id.small_brush);
        smallBtn.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                drawView.setErase(true);
                drawView.setBrushSize(smallBrush);
                brushDialog.dismiss();
            }
        });
        ImageButton mediumBtn = (ImageButton)brushDialog.findViewById(R.id.medium_brush);
        mediumBtn.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                drawView.setErase(true);
                drawView.setBrushSize(mediumBrush);
                brushDialog.dismiss();
            }
        });
        ImageButton largeBtn = (ImageButton)brushDialog.findViewById(R.id.large_brush);
        largeBtn.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View v) {
                drawView.setErase(true);
                drawView.setBrushSize(largeBrush);
                brushDialog.dismiss();
            }
        });
        brushDialog.show();
    }
    else if(view.getId()==R.id.new_btn){
        //new button
    AlertDialog.Builder newDialog = new AlertDialog.Builder(this);
        newDialog.setTitle("New drawing");
        newDialog.setMessage("Start new drawing (you will lose the current drawing)?");
        newDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int which){
                drawView.startNew();
                dialog.dismiss();
            }
        });
        newDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int which){
                dialog.cancel();
            }
        });

        newDialog.show();


    }
    else if(view.getId()==R.id.save_btn){
        //save drawing
        AlertDialog.Builder saveDialog = new AlertDialog.Builder(this);
        saveDialog.setTitle("Save drawing");
        saveDialog.setMessage("Save drawing to device Gallery?");
        saveDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int which){
                //save drawing
                drawView.setDrawingCacheEnabled(true);
                //attempt to save
                String imgSaved = MediaStore.Images.Media.insertImage(
                        getContentResolver(), drawView.getDrawingCache(),
                        UUID.randomUUID().toString()+".png", "drawing");
                //feedback
                if(imgSaved!=null){
                    Toast savedToast = Toast.makeText(getApplicationContext(),
                            "Drawing saved to Gallery!", Toast.LENGTH_SHORT);
                    savedToast.show();
                }
                else{
                    Toast unsavedToast = Toast.makeText(getApplicationContext(),
                            "Oops! Image could not be saved.", Toast.LENGTH_SHORT);
                    unsavedToast.show();
                }
                drawView.destroyDrawingCache();
            }
        });
        saveDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int which){
                dialog.cancel();
            }
        });
        saveDialog.show();
    }
}
// Courtesy : developer.android.com/training/displaying-bitmaps/load-bitmap.html
public static int calculateInSampleSize(

        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        // Calculate ratios of height and width to requested height and width
        final int heightRatio = Math.round((float) height / (float) reqHeight);
        final int widthRatio = Math.round((float) width / (float) reqWidth);

        // Choose the smallest ratio as inSampleSize value, this will guarantee
        // a final image with both dimensions larger than or equal to the
        // requested height and width.
        inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }

    return inSampleSize;
}


private Bitmap getBitmapFromUri(Uri data){
    Bitmap bitmap = null;

    // Starting fetch image from file
    InputStream is=null;
    try {

        is = getContentResolver().openInputStream(data);

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        // BitmapFactory.decodeFile(path, options);
        BitmapFactory.decodeStream(is, null, options);

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, mWidth, mHeight);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;

        is = getContentResolver().openInputStream(data);

        bitmap = BitmapFactory.decodeStream(is,null,options);


        if(bitmap==null){
            Toast.makeText(getBaseContext(), "Image is not Loaded",Toast.LENGTH_SHORT).show();
            return null;
        }

        is.close();
    }catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }catch(NullPointerException e){
        e.printStackTrace();
    }
    return bitmap;
}


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    // TODO Auto-generated method stub
    super.onActivityResult(requestCode, resultCode, intent);
    if (requestCode == 10 && resultCode == RESULT_OK && null != intent) {
        Uri data = intent.getData();
        Bitmap bitmap = getBitmapFromUri(data);
        if(bitmap!=null){
            drawView.canvasBitmap=bitmap;
        }
    }
}


@Override
public void onWindowFocusChanged(boolean hasFocus) {
    // TODO Auto-generated method stub
    super.onWindowFocusChanged(hasFocus);
    mWidth = drawView.getWidth();
    mHeight = drawView.getHeight();
}

@Override
protected void onSaveInstanceState(Bundle outState) {

    outState.putInt("width", mWidth);
    outState.putInt("height", mHeight);
    if(drawView.canvasBitmap!=null){
        outState.putParcelable("bitmap", drawView.canvasBitmap);
    }

    super.onSaveInstanceState(outState);

}
}
Posted

1 solution

C#
case MotionEvent.ACTION_UP:
    drawPath.lineTo(touchX, touchY);
    drawCanvas.drawPath(drawPath, drawPaint);
    drawPath.reset();// this line is the issue, on Touch_Up you're resetting the drawPath, which means whatever changes you've made so far, it'd be all gone.

-KR
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900