For this week's hand in we have had to
develop an application which allows the user to draw on the screen
using gestures.
Our application (see the screen shot
below) includes several controls for the app, controls like clearing
the screen, increase or decrease the size of the dots, selecting the
color, draw different shapes (dots, lines, squares and circles) and
also controls for undoing and redoing.
The main view of the application
consists of a view with a linear layout (with vertical orientation)
which nests a draw view as it's first child and the controls as the
second child. The reason for using a nested view is purely esthetic,
its role being to hold the drawing area on top of the screen and the
controls on the bottom.
The drawing is done by using an
ArrayList of DrawingElement and than in the onDraw() method just
paint all the elements in the ArrayList on the screen.
In order to be able to store all the
elements the application uses the onTouch() method together with the
actions provides by the event calling this method.
Each DrawingElement contains fields for
storing the x and y coordinates when the user touches the screen and
x and y coordinates for the case when the user releases the screen
(these last two coordinates help in drawing all the figures except
for the dots). The element also contains fields for storing the color
the element has, its type and also its size (in case of the dots).
After each element is stored the
invalidate() method is called in order to tell the AndroidOS to draw
every element on the screen.
One could thing is that the user can select the color to draw with by using the color control. This control opens a ColorPickerDialog which changes the value of the color field in the DrawView (the nested view):
It is able to change the value of the color field because the nested view implements the ColorPickerDialog.OnColorChangedListener and than because I have implemented the colorChanged() method required for the listener:
public void colorChanged(int color) {
paint.setColor(color);
}
Another cool thing about the application is
that it allows the user to see the size of the shapes he is drawing
while dragging on the screen. This is done by implementing the case
of MotionEvent.MOTION_MOVE. The code snippet below demonstrates this
case:
in the onTouch(View view, MotionEvent
event) method:
if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (moveFlag == 1 && elements.size() != 0) {
if (lineFlag == 1 || circleFlag == 1 || squareFlag == 1) {
// remove the element added by the move event
elements.remove(elements.size() - 1);
}
}
// get the end point of the line
element.x2 = event.getX();
element.y2 = event.getY();
element.color = paint.getColor();
element.size = drawSize;
if (dotFlag == 1) {
element.type = 1;
} else if (lineFlag == 1) {
element.type = 2;
} else if (circleFlag == 1) {
element.type = 3;
} else if (squareFlag == 1) {
element.type = 4;
}
// prepare a temporary element to be added to the array of
// drawing elements
DrawingElement tempElement = new DrawingElement();
tempElement.x1 = element.x1;
tempElement.y1 = element.y1;
tempElement.x2 = element.x2;
tempElement.y2 = element.y2;
tempElement.type = element.type;
tempElement.color = element.color;
tempElement.size = element.size;
elements.add(tempElement);
invalidate();
if (moveFlag == 0) {
if (lineFlag == 1 || circleFlag == 1 || squareFlag == 1) {
moveFlag = 1;
}
}
}
One other cool thing for the
application is that the user can undo and redo all of his actions.
This has been achieved using a stack to push the elements when the
user select the undo control and pop the elements when the user
selects the redo control.
public boolean onUndoClick() {
if (elements.size() != 0) {
// get the last elements
DrawingElement d = elements.get(elements.size() - 1);
// remove last element from the elements array
elements.remove(elements.size() - 1);
// insert the element in the stack
undoStack.push(d);
invalidate();
// add the action to the log
Log.d(TAG, "Undo: " + d);
}
return true;
}
public boolean onRedoClick() {
if (!undoStack.isEmpty()) {
// get the last element added to the undoStack
DrawingElement d = undoStack.pop();
// add the element to the elements array
elements.add(d);
// draw the screen
invalidate();
// add the action to the log
Log.d(TAG, "Redo: " + d);
}
return true;
}
The application can be downloaded from
the link below:
The apk:
The source code:
It took me approximately 10 hours to
develop this app. I have spent most of the time dealing with the
motion event. The undo and redo controls took me approximately 10
minutes to implement. ;)
No comments:
Post a Comment