Draw on Canvas multiple times

2019-09-16 15:17发布

问题:

I've got a little problem on a exercise of my class. The exercise is to draw Shapes multiple times on Canvas. But I can only draw once, when I draw another one, the previous is deleted. Here is my CustomView code. figuras is an LinkedList of shapes that in the future I will save them. On draw i shall sraw the figures from the LinkedList.

package com.example.AndroidTest;

    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Paint.Style;
    import android.text.TextUtils;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.Toast;

    import java.util.LinkedList;

public class CustomView extends View {

private final Paint brush;
private LinkedList<Figures> figuras;
public int id;
private float startX;
private float endX;
private float startY;
private float endY;
Figures fig; // á partida é para mudar para o createFigure
public CustomView(Context context, LinkedList <Figures> figures)
{
    super(context);
    brush = new Paint();
    brush.setStyle(Style.STROKE);
    brush.setColor(Color.WHITE);
    brush.setStrokeWidth(6);
    figuras = figures;
}

@Override
protected void onDraw(Canvas canvas)
{
    super.onDraw(canvas);


        createFigure( startX,  startY,  endX,  endY);
        fig.drawFigure(canvas, brush);
        invalidate();

}

public String getString(){
    String joined = TextUtils.join("\n\n", figuras); return joined;
} // criar uma string a copiar o conteudo duma list com o intervalo de uma virgula.


@Override
public boolean onTouchEvent( MotionEvent event) {

    if (event.getAction() == event.ACTION_DOWN) {
        startY = event.getY();
        startX = event.getX();
        endY = event.getY();
        endX = event.getX();
        figuras.add(fig);
        Toast.makeText(getContext(), "" + figuras.size(), Toast.LENGTH_SHORT).show();

    } else if (event.getAction() == event.ACTION_MOVE) {
        endY = event.getY();
        endX = event.getX();
        figuras.getLast().setEndVars(endX, endY);

    }
    return super.onTouchEvent(event);
}

public void createFigure(float startX, float startY, float endX, float endY) {


    switch (id) // aqui crio a figura Fig fig = new line/circle/rect
    {
        case 0:
            fig = new Line(startX, startY, endX, endY);
            break;
        case 1:
            fig = new Circle(startX, startY, endX, endY);
            break;
        case 2:
            fig = new Rectangle(startX, startY, endX, endY);
            break;
    }
    //return fig;
}

public void setID(int aux)
{
    id = aux;
}

public LinkedList<Figures> getArray()
{
    return figuras;
}

}

回答1:

After you call invalidate everything that has been drawn will be erased and onDraw will be called again. Currently you are drawing in an infinite loop, every time drawing one figure with the current values of the startY, startX, endY and endX variables then invalidating what you have drawn. If those variables have changed the old figure will not be drawn again.

In order to draw the new figure and all the old ones as well, every time onDraw is called you would have to iterate over figuras and draw every figure again. Then you should see all figures ever added to figuras, therefore all figures you want to draw. Like this:

protected void onDraw(Canvas canvas)
{
   super.onDraw(canvas);
   for(Figures f : figuras) {
      f.drawFigure(canvas, brush);
   }
}

Two more notions on performance. You should call invalidate in your onTouchEvent and not on the onDraw. That will save a lot of calculating power. Currently i bet you can use your phone as hand warmer. Also you should create the figure in the onTouchEvent. In the onDraw only do what is necessary. Everything else should be outside of onDraw.