Finally I have made my second app in android -paint app- I was so interested in making this app because I like drawing , It’s one of my hobbies.
now let start going into the project.
This is the final result of the project .
Before drawing
After drawing
Change color
Make new page, change the size of the brush ,use eraser change the size of it, save your drawing to the gallery.
Now I will start explaining the coding part
Firstly create new android project, exactly same as previous project.
And create user interface of the app add picture buttons insert background , add dimensions for brush/eraser sizes
<!-- Brush sizes -->
<dimen name="small_brush">10dp</dimen>
<integer name="small_size">10</integer>
<dimen name="medium_brush">20dp</dimen>
<integer name="medium_size">20</integer>
<dimen name="large_brush">30dp</dimen>
<integer name="large_size">30</integer>
,add strings for new page ,brush ,eraser,save, and paint.
<string name="start_new">New</string>
<string name="brush">Brush</string>
<string name="erase">Erase</string>
<string name="save">Save</string>
<string name="paint">Paint</string>
inside the activity_main.xml i had made LinearLayout as the main layout.and drag LinearLayout inside th main main layout and to make the rows of the color i have made this for first row
<LinearLayout
android:id="@+id/paint_colors"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
and second row
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
the first row has an id because use in java class when the app starts the first default color as selected so that the user can start drawing straight away.i added a new xml file and named it "paint.xml" inside the drawable file and wrote the following code
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle" >
<stroke
android:width="4dp"
android:color="#FF999999" />
<solid android:color="#00000000" />
<padding
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp" />
</shape>
</item>
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<stroke
android:width="4dp"
android:color="#FF999999" />
<solid android:color="#00000000" />
<corners android:radius="10dp" />
</shape>
</item>
</layer-list>
it is a little complex than it looks at first glance. To create a rounded button appearance, we use two layered Shape drawables, one rectangle outline and theother a rounded stroke.The strokes have gray color , with transparency in the middle through which the background color for each button will be seen(the background color being the color represented by the button).
so, now for each color, i used the following ImageButton structure:
inside the first row LinearLayout
<ImageButton
android:layout_width="@dimen/large_brush"
android:layout_height="@dimen/large_brush"
android:layout_margin="2dp"
android:background="#FF660000"
android:contentDescription="@string/paint"
android:onClick="paintClicked"
android:src="@drawable/paint"
android:tag="#FF660000" />
<ImageButton
android:layout_width="@dimen/large_brush"
android:layout_height="@dimen/large_brush"
android:layout_margin="2dp"
android:background="#FFFF0000"
android:contentDescription="@string/paint"
android:onClick="paintClicked"
android:src="@drawable/paint"
android:tag="#FFFF0000" />
<ImageButton
android:layout_width="@dimen/large_brush"
android:layout_height="@dimen/large_brush"
android:layout_margin="2dp"
android:background="#FFFF6600"
android:contentDescription="@string/paint"
android:onClick="paintClicked"
android:src="@drawable/paint"
android:tag="#FFFF6600" />
<ImageButton
android:layout_width="@dimen/large_brush"
android:layout_height="@dimen/large_brush"
android:layout_margin="2dp"
android:background="#FFFFCC00"
android:contentDescription="@string/paint"
android:onClick="paintClicked"
android:src="@drawable/paint"
android:tag="#FFFFCC00" />
<ImageButton
android:layout_width="@dimen/large_brush"
android:layout_height="@dimen/large_brush"
android:layout_margin="2dp"
android:background="#FF009900"
android:contentDescription="@string/paint"
android:onClick="paintClicked"
android:src="@drawable/paint"
android:tag="#FF009900" />
<ImageButton
android:layout_width="@dimen/large_brush"
android:layout_height="@dimen/large_brush"
android:layout_margin="2dp"
android:background="#FF009999"
android:contentDescription="@string/paint"
android:onClick="paintClicked"
android:src="@drawable/paint"
android:tag="#FF009999" />
inside the second row LinearLayout
<ImageButton
android:layout_width="@dimen/large_brush"
android:layout_height="@dimen/large_brush"
android:layout_margin="2dp"
android:background="#FF0000FF"
android:contentDescription="@string/paint"
android:onClick="paintClicked"
android:src="@drawable/paint"
android:tag="#FF0000FF" />
<ImageButton
android:layout_width="@dimen/large_brush"
android:layout_height="@dimen/large_brush"
android:layout_margin="2dp"
android:background="#FF990099"
android:contentDescription="@string/paint"
android:onClick="paintClicked"
android:src="@drawable/paint"
android:tag="#FF990099" />
<ImageButton
android:layout_width="@dimen/large_brush"
android:layout_height="@dimen/large_brush"
android:layout_margin="2dp"
android:background="#FFFF6666"
android:contentDescription="@string/paint"
android:onClick="paintClicked"
android:src="@drawable/paint"
android:tag="#FFFF6666" />
<ImageButton
android:layout_width="@dimen/large_brush"
android:layout_height="@dimen/large_brush"
android:layout_margin="2dp"
android:background="#FFFFFFFF"
android:contentDescription="@string/paint"
android:onClick="paintClicked"
android:src="@drawable/paint"
android:tag="#FFFFFFFF" />
<ImageButton
android:layout_width="@dimen/large_brush"
android:layout_height="@dimen/large_brush"
android:layout_margin="2dp"
android:background="#FF787878"
android:contentDescription="@string/paint"
android:onClick="paintClicked"
android:src="@drawable/paint"
android:tag="#FF787878" />
<ImageButton
android:layout_width="@dimen/large_brush"
android:layout_height="@dimen/large_brush"
android:layout_margin="2dp"
android:background="#FF000000"
android:contentDescription="@string/paint"
android:onClick="paintClicked"
android:src="@drawable/paint"
android:tag="#FF000000" />
i used one of the dimension values that i had defined for th color button.
after finishing the user interface i started to implement drawing on the canvas and choosing colors.
create new class named it DrawingView and extends View and then define all the variables that i will use:
//drawing path
private Path drawPath;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//initial color
private int paintColor = 0xFF660000;
//canvas
private Canvas drawCanvas;
//canvas bitmap
private Bitmap canvasBitmap;
when the user touches the screen and moves their finger to draw, I used a path to trace their drawing actin on the canvas.Both the canvas and the drawing on top of it are represented by paint objects. The initial paint color corresponds to the first color in the palette i had created before , which will be initiallly selected when the app launches. Finally i declared variables for the canvas and bitmap- the user paths drawn with drawPaint wil be drawn onto the canvas, which is drawn with canvasPaint.
added new method and named it setupDrawing and instantiate some of these variables to set set the class up for drawing .
first instantiate the drawing Path and Paint objects
next set the initial color
and then set the initail path properties:
drawPath = new Path();
drawPaint = new Paint();
//drawPaint.setColor(paintColor);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(20);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
complete the setupDrawing method by instantiating the canvas Paint object:
canvasPaint = new Paint(Paint.DITHER_FLAG);
i set dithering by passing a parameter to constructor.
then override the couple of methods to make the custom view function as a drawing view.
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//view given size
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
}
@Override
protected void onDraw(Canvas canvas) {
//draw view
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
}
when the drawing view is on the app screen, we want user touches on it to regester as drawing operations.
to do this we need to listen for touch events.
public boolean onTouchEvent(MotionEvent event) {
//detect user touch
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawPath.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
drawPath.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
break;
default:
return false;
}
invalidate();
return true;//Calling invalidate will cause the onDraw method to execute.
}
The MotionEvent parameter to the onTouchEvent method will let us respond to particular touch events. the actions we are interesteed in to implement drawing are down,move and up. Added a switch statement in the method to respond .
when the user touches the view, we move to that position to start drawing. when they move thier finger on the View wedraw the path along with their touch. when they lift their finger up off the view , we draw the path and reset it for the next drawing operation.
Let's now talk about implementing the ability for the user to choose colors from the palette.
inside main activity class inside onCreate methode i instantiated variables by retrieving a reference to it from the layout:
drawView = (DrawingView)findViewById(R.id.drawing);
LinearLayout paintLayout = (LinearLayout)findViewById(R.id.paint_colors);
currPaint = (ImageButton)paintLayout.getChildAt(0);
currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
smallBrush = getResources().getInteger(R.integer.small_size);
mediumBrush = getResources().getInteger(R.integer.medium_size);
largeBrush = getResources().getInteger(R.integer.large_size);
drawBtn = (ImageButton)findViewById(R.id.draw_btn);
drawBtn.setOnClickListener(this);
drawView.setBrushSize(mediumBrush);
eraseBtn = (ImageButton)findViewById(R.id.erase_btn);
eraseBtn.setOnClickListener(this);
newBtn = (ImageButton)findViewById(R.id.new_btn);
newBtn.setOnClickListener(this);
saveBtn = (ImageButton)findViewById(R.id.save_btn);
saveBtn.setOnClickListener(this);
get the fir button and store it as the instance varable and use different drawable image on the button to show that it is currently selected:
currPaint = (ImageButton)paintLayout.getChildAt(0);
currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
i added this new "paint_pressed.xml" file inside drawable file and wrote the following code
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<shape android:shape="rectangle" >
<stroke
android:width="4dp"
android:color="#FF333333" />
<solid android:color="#00000000" />
<padding
android:bottom="0dp"
android:left="0dp"
android:right="0dp"
android:top="0dp" />
</shape>
</item>
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<stroke
android:width="4dp"
android:color="#FF333333" />
<solid android:color="#00000000" />
<corners android:radius="10dp" />
</shape>
</item>
</layer-list>
it is very similar to the"paint.xml"drawable we created last time, but with darker color around the paint.
I went go back to main activity class and added paintClicked method
public void paintClicked(View view){
//use chosen color
if(view!=currPaint){
//update color
ImageButton imgView = (ImageButton)view;
String color = view.getTag().toString();
drawView.setColor(color);
imgView.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint));
currPaint=(ImageButton)view;
}
}
first check that the user has clicked a paint color that is not the currently selected one,then retrieve the tag we set for each button in the layout , representing the chosen color.
then i needed to use the custom View class to set the color , so i added set color in side Drawing View class
public void setColor(String newColor){
//set color
invalidate();
paintColor = Color.parseColor(newColor);
drawPaint.setColor(paintColor);
}
start by invalidating th View , then set the color for drawing, now going back to the main activity, in paintClicked method after retriving the color tag , call the new method on the custom drawing View object and then update th user interface to reflect the new chosen paint and set the previouse one back to the normal.
now i will discuss the last part of my project. About the ability to erase to create new drawing page ,to save a drawing to the gallary of your device.
in the previouse part i discussed about drawing on the canvas, then now i will discuss how to make the user choose a brush size. The brush size options will appear when the user presses the brush button I added t the interface. To respond to this, extend the opening line of in main activity class declaration to the implement the OnClickListener interface:
public class MainActivity extends Activity implements OnClickListener
override onClick method and check for clicks on the drawing button using if statement
@Override
public void onClick(View view){
//respond to clicks
if(view.getId()==R.id.draw_btn){
//draw button clicked
final Dialog brushDialog = new Dialog(this);
brushDialog.setTitle("Brush size:");
}
}
there are another coditional blocks i will speak about them later.When the user clicks the button i already displayed a dialog presenting them with the three button sizes.Inside the if block, and create a dialog and set the titleThen i defined the dialog layout in "brush_chooser.xml" inside layout file and entering the following code and inside the Layout ,added a button for each size:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >
<ImageButton
android:id="@+id/small_brush"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/sml"
android:src="@drawable/small" />
<ImageButton
android:id="@+id/medium_brush"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/med"
android:src="@drawable/medium" />
<ImageButton
android:id="@+id/large_brush"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/lrg"
android:src="@drawable/large" />
</LinearLayout>
then dd specified strings to "string.xml" Small ,Medium,Large then add three xml files for each of them
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:dither="true"
android:shape="oval" >
<size
android:height="@dimen/small_brush"
android:width="@dimen/small_brush" />
<solid android:color="#FF666666" />
</shape>
"medium.xml"
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:dither="true"
android:shape="oval" >
<size
android:height="@dimen/medium_brush"
android:width="@dimen/medium_brush" />
<solid android:color="#FF666666" />
</shape>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:dither="true"
android:shape="oval" >
<size
android:height="@dimen/large_brush"
android:width="@dimen/large_brush" />
<solid android:color="#FF666666" />
</shape>
created the dialog and set its title in main activity class in side onClick method.
brushDialog.setContentView(R.layout.brush_chooser);
i added two instance variables to the class:
private float brushSize, lastBrushSize;
and used the first varriable for the brush size and the second to keep track of the last brush size used when the user switches to the user switches to the eraser, so that we can revert back to the correct size when they decide to switch back to drawing. In the setupDrawing method .
brushSize = getResources().getInteger(R.integer.medium_size);
lastBrushSize = brushSize;
after that I used the dimension value for the medium sized brush to begin with. then I could update the line in the method where I set the stroke width with a hard coded value to use this varable value instead:
drawPaint.setStrokeWidth(brushSize);
then Added th following method to the class to set the brush size and update the brush size:
public void setBrushSize(float newSize){
//update size
float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
newSize, getResources().getDisplayMetrics());
brushSize=pixelAmount;
drawPaint.setStrokeWidth(brushSize);
}
then passing the value from the dimensions file when I call this method, so I have to calculate it's dimension value.I update the variable and the paint object to use the new size .then ass methods to get and set the other size variable I created:
public void setLastBrushSize(float lastSize){
lastBrushSize=lastSize;
}
public float getLastBrushSize(){
return lastBrushSize;
}
I called these methods from the main Activity class.
ImageButton smallBtn = (ImageButton)brushDialog.findViewById(R.id.small_brush);
smallBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
drawView.setBrushSize(smallBrush);
drawView.setLastBrushSize(smallBrush);
brushDialog.dismiss();
}
});
I set the size using the methods we added to the custom View class as soon as the user clicks a brush size button, then immediately dismiss the Dialog. next did the same for medium and large buttons:
ImageButton mediumBtn = (ImageButton)brushDialog.findViewById(R.id.medium_brush);
mediumBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
drawView.setBrushSize(mediumBrush);
drawView.setLastBrushSize(mediumBrush);
brushDialog.dismiss();
}
});
ImageButton largeBtn = (ImageButton)brushDialog.findViewById(R.id.large_brush);
largeBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
drawView.setBrushSize(largeBrush);
drawView.setLastBrushSize(largeBrush);
brushDialog.dismiss();
}
});
then completed the draw button section of onClick by displaying the dialog:
brushDialog.show();
The dialog will display until the user makes a selection or goes back to the Activity.
then used the new method to set the initial brush size in onCreate:
drawView.setBrushSize(mediumBrush);
for erasing , reset the drawing page (new drawings),saving you understand by reading my code because little differences with the previouse one .I won't discuss about it .
//MainActivity.java
package com.example.paint;
public class MainActivity extends Activity implements OnClickListener {
private DrawingView drawView;
private ImageButton currPaint, drawBtn,eraseBtn,newBtn, saveBtn;
private float smallBrush, mediumBrush, largeBrush;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
drawView = (DrawingView)findViewById(R.id.drawing);
LinearLayout paintLayout = (LinearLayout)findViewById(R.id.paint_colors);
currPaint = (ImageButton)paintLayout.getChildAt(0);
currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
smallBrush = getResources().getInteger(R.integer.small_size);
mediumBrush = getResources().getInteger(R.integer.medium_size);
largeBrush = getResources().getInteger(R.integer.large_size);
drawBtn = (ImageButton)findViewById(R.id.draw_btn);
drawBtn.setOnClickListener(this);
drawView.setBrushSize(mediumBrush);
eraseBtn = (ImageButton)findViewById(R.id.erase_btn);
eraseBtn.setOnClickListener(this);
newBtn = (ImageButton)findViewById(R.id.new_btn);
newBtn.setOnClickListener(this);
saveBtn = (ImageButton)findViewById(R.id.save_btn);
saveBtn.setOnClickListener(this);
}
public void paintClicked(View view){
drawView.setErase(false);
drawView.setBrushSize(drawView.getLastBrushSize());
//use chosen color
if(view!=currPaint){
//update color
ImageButton imgView = (ImageButton)view;
String color = view.getTag().toString();
drawView.setColor(color);
imgView.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint));
currPaint=(ImageButton)view;
}
}
@Override
public void onClick(View view){
//respond to clicks
if(view.getId()==R.id.draw_btn){
//draw button clicked
final Dialog brushDialog = new Dialog(this);
brushDialog.setTitle("Brush size:");
brushDialog.setContentView(R.layout.brush_chooser);
ImageButton smallBtn = (ImageButton)brushDialog.findViewById(R.id.small_brush);
smallBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
drawView.setBrushSize(smallBrush);
drawView.setLastBrushSize(smallBrush);
drawView.setErase(false);
brushDialog.dismiss();
}
});
ImageButton mediumBtn = (ImageButton)brushDialog.findViewById(R.id.medium_brush);
mediumBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
drawView.setBrushSize(mediumBrush);
drawView.setLastBrushSize(mediumBrush);
drawView.setErase(false);
brushDialog.dismiss();
}
});
ImageButton largeBtn = (ImageButton)brushDialog.findViewById(R.id.large_brush);
largeBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
drawView.setBrushSize(largeBrush);
drawView.setLastBrushSize(largeBrush);
drawView.setErase(false);
brushDialog.dismiss();
}
});
brushDialog.show();
}
else if(view.getId()==R.id.erase_btn){
//switch to erase - choose size
final Dialog brushDialog = new Dialog(this);
brushDialog.setTitle("Eraser size:");
brushDialog.setContentView(R.layout.brush_chooser);
ImageButton smallBtn = (ImageButton)brushDialog.findViewById(R.id.small_brush);
smallBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
drawView.setErase(true);
drawView.setBrushSize(smallBrush);
brushDialog.dismiss();
}
});
ImageButton mediumBtn = (ImageButton)brushDialog.findViewById(R.id.medium_brush);
mediumBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
drawView.setErase(true);
drawView.setBrushSize(mediumBrush);
brushDialog.dismiss();
}
});
ImageButton largeBtn = (ImageButton)brushDialog.findViewById(R.id.large_brush);
largeBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
drawView.setErase(true);
drawView.setBrushSize(largeBrush);
brushDialog.dismiss();
}
});
brushDialog.show();
}
else if(view.getId()==R.id.new_btn){
//new button
AlertDialog.Builder newDialog = new AlertDialog.Builder(this);
newDialog.setTitle("New drawing");
newDialog.setMessage("Start new drawing (you will lose the current drawing)?");
newDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which){
drawView.startNew();
dialog.dismiss();
}
});
newDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which){
dialog.cancel();
}
});
newDialog.show();
}
else if(view.getId()==R.id.save_btn){
//save drawing
AlertDialog.Builder saveDialog = new AlertDialog.Builder(this);
saveDialog.setTitle("Save drawing");
saveDialog.setMessage("Save drawing to device Gallery?");
saveDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which){
//save drawing
}
});
saveDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which){
dialog.cancel();
}
});
saveDialog.show();
drawView.setDrawingCacheEnabled(true);
//write the image to a file:
String imgSaved = MediaStore.Images.Media.insertImage(
getContentResolver(), drawView.getDrawingCache(),
UUID.randomUUID().toString()+".png", "drawing");
if(imgSaved!=null){
Toast savedToast = Toast.makeText(getApplicationContext(),
"Drawing saved to Gallery!", Toast.LENGTH_SHORT);
savedToast.show();
}
else{
Toast unsavedToast = Toast.makeText(getApplicationContext(),
"Oops! Image could not be saved.", Toast.LENGTH_SHORT);
unsavedToast.show();
}
drawView.destroyDrawingCache();
}
}
}
//DrawingView.java
package com.example.paint;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.view.MotionEvent;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.TypedValue;
public class DrawingView extends View{
//drawing path
private Path drawPath;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//initial color
private int paintColor = 0xFF660000;
//canvas
private Canvas drawCanvas;
//canvas bitmap
private Bitmap canvasBitmap;
private DrawingView drawView;
private float brushSize, lastBrushSize;
private boolean erase=false;
public DrawingView(Context context) {
super(context);
}
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
setupDrawing();
}
private void setupDrawing(){
//get drawing area setup for interaction
brushSize = getResources().getInteger(R.integer.medium_size);
lastBrushSize = brushSize;
brushSize = getResources().getInteger(R.integer.medium_size);
lastBrushSize = brushSize;
drawPath = new Path();
drawPaint = new Paint();
drawPaint.setColor(paintColor);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(20);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//view given size
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
}
@Override
protected void onDraw(Canvas canvas) {
//draw view
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//detect user touch
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawPath.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
drawPath.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
break;
default:
return false;
}
invalidate();
return true;//Calling invalidate will cause the onDraw method to execute.
}
public void setColor(String newColor){
//set color
invalidate();
paintColor = Color.parseColor(newColor);
drawPaint.setColor(paintColor);
}
public void setBrushSize(float newSize){
//update size
float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
newSize, getResources().getDisplayMetrics());
brushSize=pixelAmount;
drawPaint.setStrokeWidth(brushSize);
}
public void setLastBrushSize(float lastSize){
lastBrushSize=lastSize;
}
public float getLastBrushSize(){
return lastBrushSize;
}
public void setErase(boolean isErase){
//set erase true or false
erase=isErase;
if(erase) drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
else drawPaint.setXfermode(null);
}
public void startNew(){
drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
}
}