2

I'm trying to draw on a canvas then onClick change it to bitmap image then I would like to make it draggable. I can draw on canvas successfully but how do I convert this drawing to an image then make it draggable? I don't mind If it's possible to drag the drawing without converting to an image. Can someone please help.

public class MainActivity extends AppCompatActivity implements ColorPickerDialog.OnColorChangedListener {

    protected DrawView canvasView;
    private ImageButton blackCircle;
    private Button pens,select;
    private Paint mPaint;
    Bitmap viewCapture = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mPaint = new Paint();

        canvasView = (DrawView) findViewById(R.id.canvas_view);//The drawing mechanism
        colorChanged(mPaint.getColor());

        blackCircle = (ImageButton) findViewById(R.id.black_circle);           
        blackCircle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                canvasView.setPathColor(Color.BLACK));
                blackCircle.setPressed(true);
            }
        });

        select = (Button) findViewById(R.id.ic_select);
        select.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {

                canvasView.setVisibility(View.VISIBLE);
                canvasView.setPathColor(0);
                //Drag the drawn image
                setContentView(R.layout.activity_main);
                relativeLayout = (RelativeLayout) findViewById(R.id.main);
                drawingView = new DrawingView(MainActivity.this);
                relativeLayout.addView(drawingView);

                //Create a bitmap image of current drawing
                canvasView.setDrawingCacheEnabled(true);
                viewCapture = Bitmap.createBitmap(canvasView.getDrawingCache());
                canvasView.setDrawingCacheEnabled(false);
            }
        });

    }// End of Create();

    private void clearCanvas(View v) {
        canvasView.clear();
    }       

@Override
public void colorChanged(int color) {
    mPaint.setColor(color);
    canvasView.setPathColor(mPaint.getColor());
}


/**************   OnTouch ***************/

class DrawingView extends View{
    float x,y;

    public DrawingView(Context context){
        super(context);
        viewCapture = BitmapFactory.decodeResource(context.getResources(), R.id.main);
    }

    public boolean onTouchEvent(MotionEvent event){
        switch(event.getAction()){
            case MotionEvent.ACTION_DOWN:
            break;
            case MotionEvent.ACTION_MOVE:
                x =(int)event.getX();
                y =(int)event.getY();
                invalidate();
            break;
            case MotionEvent.ACTION_UP:
                x =(int)event.getX();
                y =(int)event.getY();
                invalidate();
            break;
        }
        return true;
    }

    @Override
    public void onDraw(Canvas canvas) {
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.CYAN);
        canvas.drawBitmap(viewCapture, x, y, paint); 
    }
  }
}//End of Class


public class DrawView extends View {

private Paint drawPaint, canvasPaint;
private Canvas drawCanvas;
private Bitmap canvasBitmap;
private SparseArray<Path> paths;

public DrawView(Context context) {
    super(context);
    setupDrawing();
}

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

public DrawView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    setupDrawing();
}

private void setupDrawing() {
    paths = new SparseArray<>();
    drawPaint = new Paint();
    drawPaint.setColor(Color.BLACK);
    drawPaint.setAntiAlias(true);
    drawPaint.setStrokeWidth(9);
    drawPaint.setStyle(Paint.Style.STROKE);
    drawPaint.setStrokeJoin(Paint.Join.ROUND);
    drawPaint.setStrokeCap(Paint.Cap.ROUND);
    canvasPaint = new Paint(Paint.DITHER_FLAG);
}

@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);
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
    for (int i=0; i<paths.size(); i++) {
        canvas.drawPath(paths.valueAt(i), drawPaint);
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    int index = event.getActionIndex();
    int id = event.getPointerId(index);

    Path path;
    switch (event.getActionMasked()) {
        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_POINTER_DOWN:
            path = new Path();
            path.moveTo(event.getX(index), event.getY(index));
            paths.put(id, path);
            break;

        case MotionEvent.ACTION_MOVE:
            for (int i=0; i<event.getPointerCount(); i++) {
                id = event.getPointerId(i);
                path = paths.get(id);
                if (path != null) path.lineTo(event.getX(i), event.getY(i));
            }
            break;

        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_POINTER_UP:
            path = paths.get(id);
            if (path != null) {
                drawCanvas.drawPath(path, drawPaint);
                paths.remove(id);
            }
            break;
        default:
            return false;
    }
    invalidate();
    return true;
}

public void setPathColor(int color) {
    drawPaint.setColor(color);
}

public void clear() {
    canvasBitmap.eraseColor(Color.TRANSPARENT);
    paths.clear();
    invalidate();
    System.gc();
 }
}
Tony
  • 529
  • 2
  • 6
  • 24

1 Answers1

0

For the next steps I assume you'd like to let the users drag the picture which they just created with the DrawView. So I'd introduce another View which can display the bitmap and set its position and dimensions exactly like those of the DrawView. (The best way to achieve this depends on the type of ViewGroup you are using)

Create a bitmap from the canvas as shown in converting a canvas into bitmap image in android

Set the bitmap as the new View's background with setBackground(Drawable), toggle the visibility of both Views as needed.

To make the new View draggable, use a View.OnTouchListener and change the position according to the MotionEvents

Another option: just drag the DrawView by using a flag to indicate whether the users can drag it or draw on it. You override onTouchEvent() already, now check the flag first and if it is set to "drag" then evaluate the delta between two MOVEs and adjust the position accordingly.

Bö macht Blau
  • 12,820
  • 5
  • 40
  • 61
  • My MainActivity class is updated now and works, a small issue though when image is dragged it's jumping and not a smooth drag, I'm not so sure how to achieve this ? – Tony Aug 16 '18 at 09:02
  • @Tony - there is some sample code [here](https://developer.android.com/training/gestures/viewgroup) which suggests using something called "touch slop" . I think it's useful for achieving a smooth movement because it helps you to ignore small deviations from the general direction of the drag – Bö macht Blau Aug 16 '18 at 17:19