Add shapes to existing canvas from a MenuItem

having a canvas with a shape drawn into it, I want to add another shape (e.g another line) when I click a MenuItem. I have not found the way to do it. This is a simplified code to try to find a solution:

public class MainActivity extends AppCompatActivity {
  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));   
    }

    public class MyView extends View {
        public MyView(Context context){
            super(context);
        }

        @Override protected void onDraw(Canvas canvas){
        Paint myPaint=new Paint();
        myPaint.setColor(Color.BLUE);
        myPaint.setStrokeWidth(8);
        canvas.drawLine(200,300,280,450,myPaint);
        }
    }

    @Override public boolean onCreateOptionsMenu(Menu menuP){
        getMenuInflater().inflate(R.menu.menu,menuP);
        return true;
    }

    @Override public boolean onOptionsItemSelected(MenuItem option_menu){
        int id=option_menu.getItemId();
        if(id==R.id.addDraw)
        {   
            //Add method to draw another shape
            return true;
        }
        return super.onOptionsItemSelected(option_menu);
    }
}

Thank you.

To force redrawing you must call invalidate(). It will cause onDraw() method to be called again, so you need to save whatever you have drawn until then and redraw everything with new shape you want. Below is a way to do this.

Tip : Do all your initialization outside onDraw() method for better performance.

  1. Create a list to store you paths.
 public class MyView extends View {
        List<Path> paths = new ArrayList<>();    // the list stores all your path
        Paint myPaint = new Paint();    // initialize the paint
        myPaint.setColor(Color.BLUE);
        myPaint.setStrokeWidth(8);
        public MyView(Context context){
            super(context);
            // you can add the initial path here
            Path path = new Path();
            path.moveTo(200f,300f);
            path.lineTo(280f, 450f);
            paths.add(path);
        }
    }
  1. Expose a public method to add path to your list
 public addPath(Path path){
    paths.add(path);
    invalidate();   // call invalidate to force re-drawing
 }
  1. Change your onDraw method to draw whatever is in the list
 @Override
    protected void onDraw(Canvas canvas) {
        for (Path p : paths) {
            canvas.drawPath(p, myPaint);
        }
    }
  1. Create an object of your custom view
public class MainActivity extends AppCompatActivity {
    private MyView canvasView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        canvasView = new MyView(this);
        setContentView(canvasView);   
    }
}
  1. Add a new path to you canvasView when needed
@Override public boolean onOptionsItemSelected(MenuItem option_menu){
        int id=option_menu.getItemId();
        if(id==R.id.addDraw)
        {   
            Path path = new Path(); // new path object
            // create the required shape using this path
            path.moveTo(5f,5f);
            path.lineTo(10f,10f);
            path.addCircle(10f, 10f, 5f, Path.Direction.CCW);
            
            // add the path to the canvasView
            canvasView.addPath(path);
            return true;
        }
        return super.onOptionsItemSelected(option_menu);
    }

Leave a Comment