second project in android ((paint app))

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 

 

"small.xml"
<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>
  "large.xml"
<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.  went back to the main activity class, l complete the dialog code in the onClick method.After setting  the content view on then dialog object, listen for clicks on the three size buttons, starting with the small one :
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 . This all my code:
//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();
	}
}

   It was awesome experience while doing this project .If there is any questions you can ask I will try to answer.   

猜你喜欢

转载自entesar.iteye.com/blog/2382441