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.