In this article, we will develop an Android application which picks up an image from an external application like Gallery, Dropbox, Google Drive etc and draw it in a view canvas.
This application is developed in Eclipse 4.2.0 with ADT Plugin (22.0.1) and Android SDK ( 22.0.1 ) .
1. Create a new Android application project namely “GraphicsPickImageViewCanvas”
2. Configure the project
3. Design application launcher icon
4. Create a blank activity
5. Enter MainActivity details
6. Update the file res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Pick and Draw Image</string> <string name="action_settings">Settings</string> <string name="hello_world">Hello world!</string> <string name="pick">Pick an image</string> </resources>
7. Create a java class file src/in/wptrafficanalyzer/graphicspickimageviewcanvas/PaintView.java
package in.wptrafficanalyzer.graphicspickimageviewcanvas; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Matrix.ScaleToFit; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View; public class PaintView extends View{ Paint mPaint; Bitmap mBitmap; Matrix mMatrix; RectF mSrcRectF; RectF mDestRectF; boolean mPause; public PaintView(Context context,AttributeSet attributeSet){ super(context,attributeSet); mPaint = new Paint(); mMatrix = new Matrix(); mSrcRectF = new RectF(); mDestRectF = new RectF(); mPause = false; } public void addBitmap(Bitmap bitmap){ mBitmap = bitmap; } public Bitmap getBitmap(){ return mBitmap; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if(!mPause){ if(mBitmap!=null){ // Setting size of Source Rect mSrcRectF.set(0, 0,mBitmap.getWidth(),mBitmap.getHeight()); // Setting size of Destination Rect mDestRectF.set(0, 0, getWidth(), getHeight()); // Scaling the bitmap to fit the PaintView mMatrix.setRectToRect( mSrcRectF , mDestRectF, ScaleToFit.CENTER); // Drawing the bitmap in the canvas canvas.drawBitmap(mBitmap, mMatrix, mPaint); } // Redraw the canvas invalidate(); } } // Pause or resume onDraw method public void pause(boolean pause){ mPause = pause; } }
8. Update the layout file res/layout/activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <Button android:id="@+id/btn_pick" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:text="@string/pick" /> <in.wptrafficanalyzer.graphicspickimageviewcanvas.PaintView android:id="@+id/paint_view" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_above="@id/btn_pick" /> </RelativeLayout>
9. Update the class src/in/wptrafficanalyzer/graphicspickimageviewcanvas/MainActivity.java
package in.wptrafficanalyzer.graphicspickimageviewcanvas; import java.io.IOException; import java.io.InputStream; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class MainActivity extends Activity { PaintView mPaintView; Button mBtnPick; int mWidth; int mHeight; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mWidth = mHeight = 0; // Getting reference to PaintView mPaintView = (PaintView) findViewById(R.id.paint_view); // Getting reference to Button "Pick an Image" mBtnPick = (Button) findViewById(R.id.btn_pick); // Setting OnClickListener for the button mBtnPick.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Intent i = new Intent(); i.setType("image/*"); i.setAction(Intent.ACTION_GET_CONTENT); Intent customChooserIntent = Intent.createChooser(i, "Pick an image"); startActivityForResult(customChooserIntent, 10); } }); if(savedInstanceState!=null){ mWidth = savedInstanceState.getInt("width"); mHeight = savedInstanceState.getInt("height"); Bitmap bitmap = savedInstanceState.getParcelable("bitmap"); if(bitmap!=null){ mPaintView.addBitmap(bitmap); } } } // Courtesy : developer.android.com/training/displaying-bitmaps/load-bitmap.html public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { // Calculate ratios of height and width to requested height and width final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); // Choose the smallest ratio as inSampleSize value, this will guarantee // a final image with both dimensions larger than or equal to the // requested height and width. inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; } private Bitmap getBitmapFromUri(Uri data){ Bitmap bitmap = null; // Starting fetch image from file InputStream is=null; try { is = getContentResolver().openInputStream(data); // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // BitmapFactory.decodeFile(path, options); BitmapFactory.decodeStream(is, null, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, mWidth, mHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; is = getContentResolver().openInputStream(data); bitmap = BitmapFactory.decodeStream(is,null,options); if(bitmap==null){ Toast.makeText(getBaseContext(), "Image is not Loaded",Toast.LENGTH_SHORT).show(); return null; } is.close(); }catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }catch(NullPointerException e){ e.printStackTrace(); } return bitmap; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { // TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, intent); if (requestCode == 10 && resultCode == RESULT_OK && null != intent) { Uri data = intent.getData(); Bitmap bitmap = getBitmapFromUri(data); if(bitmap!=null){ mPaintView.addBitmap(bitmap); } } } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); mWidth = mPaintView.getWidth(); mHeight = mPaintView.getHeight(); } @Override protected void onSaveInstanceState(Bundle outState) { outState.putInt("width", mWidth); outState.putInt("height", mHeight); if(mPaintView.getBitmap()!=null){ outState.putParcelable("bitmap", mPaintView.getBitmap()); } super.onSaveInstanceState(outState); } @Override protected void onResume() { mPaintView.pause(false); // Resume repainting mPaintView.invalidate(); super.onResume(); } @Override protected void onPause() { // Pause repainting mPaintView.pause(true); super.onPause(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
10. Screenshots of the application
11. Download Source Code


I am George Mathew, working as software architect and Android app developer at wptrafficanalyzer.in
You can hire me on hourly basis or on project basis for Android applications development.
For hiring me, please mail your requirements to info@wptrafficanalyzer.in.
My other blogs
store4js.blogspot.com
Thanks for this post . Helped me in adding an image to canvas but I need to add multiple images . Every time I draw a new bitmap, the old bitmap is lost . Is there method to save current state of canvas ?