Drawing a path

Some of you have wanted a way to draw a path where your character has been, or where the user has touched. You have to maintain a history of previous points, and then redraw those points (or, more likely, lines between those points) every time you invalidate the screen.

Here’s an example where we create our own View and use it as a custom view in the layout that fills the remainder of the screen.

public class MyCanvas extends View
implements View.OnTouchListener {

Inside this class, you want to declare an ArrayList. This is just a more powerful variant of an array that allows insertion and removal wherever you want.

    private ArrayList<Point> points = new ArrayList<Point>();

The type of the elements in our ArrayList is android.graphics.Point, which is really just a pair of an integer x coordinate and y coordinate. Here’s just about everything you need to know about how they work:

    // Demonstrate the Point class
    Point p = new Point(3,4)
    p.x // has the value 3
    p.y // has the value 4
    p.y++;
    // Now the point represents (3,5)

So now, when our view gets an onTouch event, we grab the coordinate at which the user touched, and add it to our points list:

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Point current = new Point();
        current.x = (int) event.getX();
        current.y = (int) event.getY();
        points.add(current);
        // If you want to limit the size of the list,
        // we can remove the first (oldest) element.
        if(points.size() > 50) {
            points.remove(0);
        }
        invalidate();
        return true;
    }

Now the onDraw method will draw lines between the points in the list. This is a little longer than it strictly needs to be, because I wanted to draw green rectangles at each point, and red lines between them.

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint red = new Paint();
        red.setColor(Color.RED);
        Paint green = new Paint();
        green.setColor(Color.GREEN);
        if(points.size() > 0) {
            // Draw point itself, as a small rectangle
            Point prev = points.get(0);
            canvas.drawRect(prev.x-1, prev.y-1, prev.x+1, prev.y+1, green);
            for(int i = 1; i < points.size(); i++) {
                Point current = points.get(i);
                canvas.drawLine(prev.x, prev.y, current.x, current.y, red);
                canvas.drawRect(current.x-1, current.y-1,
                        current.x+1, current.y+1, green);
                prev = current;
            }
        }
    }

The result looks like this. You can tell that we are moving slowly when the green rectangles are close together, and faster when they are spread out.

As you trace your finger around, the other end of the line disappears, so it’s keeping at most 50 points at a time.