If you're app is consisting signature capturing/drawing feature fromuser then you can refer the below code.I have done it using View and Canvas class. In this approach you don't need to add any third party libraries or jar.This app is also saving the files into External database in JPEG image format.
Go through the following steps , Lets design the UI first for Signature and Home screen.
Step-1: Create Home screen.
I have just added on TextView and one Button. OnClick of button will take user to next screen to draw signature.
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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:background="#58FAF4" >
<Button
android:id="@+id/bsignature"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/textView1"
android:layout_marginTop="53dp"
android:text="Get Signature" />
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/signature"
android:layout_alignParentTop="true"
android:layout_marginLeft="14dp"
android:layout_marginTop="19dp"
android:text="@string/hello_world" />
</RelativeLayout>
Step-2: Design signature draw screen.
Here i have added three buttons Save,Cancel and Clear for several operations. User need to put their name in EditText.
Blank space is LinearLayout where we will add canvas to draw signature.
Blank space is LinearLayout where we will add canvas to draw signature.
signature.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#F6CEEC">
<LinearLayout android:layout_height="wrap_content"
android:id="@+id/linearLayout2"
android:layout_width="match_parent"
android:weightSum="1">
<Button android:layout_height="50dp"
android:layout_weight=".30"
android:text="Cancel"
android:layout_width="0dp"
android:id="@+id/cancel" />
<Button android:layout_height="50dp"
android:layout_weight=".35"
android:text="Clear"
android:layout_width="0dp"
android:id="@+id/clear" />
<Button android:layout_height="50dp"
android:layout_weight=".35"
android:text="Save"
android:layout_width="0dp"
android:id="@+id/getsign" />
</LinearLayout>
<TableLayout android:layout_height="wrap_content"
android:id="@+id/tableLayout1"
android:layout_width="match_parent">
<TableRow android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_height="wrap_content"
android:id="@+id/textView2"
android:text="Your Name"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content"
android:paddingLeft="10sp"
android:layout_gravity="right" />
<EditText android:layout_height="wrap_content"
android:id="@+id/yourName"
android:layout_weight="1"
android:layout_width="match_parent"
android:maxLength="30">
<requestFocus />
</EditText>
</TableRow>
<TableRow android:id="@+id/tableRow3"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_height="wrap_content"
android:id="@+id/textView2"
android:text="" android:maxLength="30"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content" />
<TextView android:layout_height="wrap_content" android:id="@+id/textView2"
android:text="Please Sign below ..." android:maxLength="30"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content" />
</TableRow>
</TableLayout>
<LinearLayout android:layout_height="match_parent"
android:id="@+id/linearLayout" android:layout_width="match_parent" />
</LinearLayout>
Step-3: Home screen java code
This file is having onclick event to goto signature draw page and it also receives the result in return.
MainActivity.java
package com.allandroidcodes.signatureinput;
import com.allandroidcodes.signatureinput.R;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Gravity;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity {
public static final int SIGNATURE_ACTIVITY = 1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button getSignature = (Button) findViewById(R.id.bsignature);
getSignature.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, TakeSignature.class);
startActivityForResult(intent,SIGNATURE_ACTIVITY);
}
});
}
//Return result to this activity
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
switch(requestCode) {
case SIGNATURE_ACTIVITY:
if (resultCode == RESULT_OK) {
Bundle bundle = data.getExtras();
String status = bundle.getString("status");
if(status.equalsIgnoreCase("done")){
Toast toast = Toast.makeText(this, "Signature captured successfully",0);
toast.setGravity(Gravity.TOP, 105, 50);
toast.show();
}
}
break;
}
}
}
Step-4: Signature draw code
Here signature drawing and saving procces is coded.
TakeSignature.java
package com.allandroidcodes.signatureinput;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Random;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.provider.MediaStore.Images;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Toast;
public class TakeSignature extends Activity {
LinearLayout mContent;
signature mSignature;
Button mClear, mGetSign, mCancel;
public static String tempDir;
public int count = 1;
public String current = null;
private Bitmap mBitmap;
View mView;
File mypath;
private String uniqueId;
private EditText yourName;
private Uri fileUri; // file url to store image
// directory name to store captured images
private static final String IMAGE_DIRECTORY_NAME = "Signaure";
File myExternalFile;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.signature);
mContent = (LinearLayout) findViewById(R.id.linearLayout);
mSignature = new signature(this, null);
mSignature.setBackgroundColor(Color.WHITE);
mContent.addView(mSignature, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
mClear = (Button)findViewById(R.id.clear);
mGetSign = (Button)findViewById(R.id.getsign);
mGetSign.setEnabled(false);
mCancel = (Button)findViewById(R.id.cancel);
mView = mContent;
yourName = (EditText) findViewById(R.id.yourName);
//clear the signature
mClear.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Log.v("log_tag", "Panel Cleared");
mSignature.clear();
mGetSign.setEnabled(false);
}
});
//save the signature
mGetSign.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Log.v("log_tag", "Panel Saved");
boolean error = captureSignature();
if(!error){
mView.setDrawingCacheEnabled(true);
mSignature.save(mView);
Bundle b = new Bundle();
b.putString("status", "done");
Intent intent = new Intent();
intent.putExtras(b);
setResult(RESULT_OK,intent);
finish();
}
}
});
//cancel and back to previous screen
mCancel.setOnClickListener(new OnClickListener()
{
public void onClick(View v)
{
Log.v("log_tag", "Panel Canceled");
Bundle b = new Bundle();
b.putString("status", "cancel");
Intent intent = new Intent();
intent.putExtras(b);
setResult(RESULT_OK,intent);
finish();
}
});
}
//method to for name validation
private boolean captureSignature() {
boolean error = false;
String errorMessage = "";
if(yourName.getText().toString().equalsIgnoreCase("")){
errorMessage = errorMessage + "Please enter your Name\n";
error = true;
}
if(error){
Toast toast = Toast.makeText(this, errorMessage, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP, 105, 50);
toast.show();
}
return error;
}
//class to captupre signature
public class signature extends View{
private static final float STROKE_WIDTH = 5f;
private static final float HALF_STROKE_WIDTH = STROKE_WIDTH / 2;
private Paint paint = new Paint();
private Path path = new Path();
private float lastTouchX;
private float lastTouchY;
private final RectF dirtyRect = new RectF();
public signature(Context context, AttributeSet attrs)
{
super(context, attrs);
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(STROKE_WIDTH);
}
public void save(View v)
{
if(mBitmap == null)
{
mBitmap = Bitmap.createBitmap (mContent.getWidth(), mContent.getHeight(), Bitmap.Config.RGB_565);;
}
Canvas canvas = new Canvas(mBitmap);
v.draw(canvas);
File myDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
IMAGE_DIRECTORY_NAME);
// Create the storage directory if it does not exist
if (!myDir.exists()) {
if (!myDir.mkdirs()) {
Toast.makeText(getApplicationContext(), "Oops..fail to create directory", 0).show();
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
String fname = "IMG_"+timeStamp +".jpg";
File file = new File (myDir, fname);
if (file.exists ()) file.delete ();
try {
FileOutputStream out = new FileOutputStream(file);
mBitmap.compress(Bitmap.CompressFormat.JPEG,100, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void clear()
{
path.reset();
invalidate();
}
//methods for motions of touch events
protected void onDraw(Canvas canvas)
{
canvas.drawPath(path, paint);
}
public boolean onTouchEvent(MotionEvent event)
{
float eventX = event.getX();
float eventY = event.getY();
mGetSign.setEnabled(true);
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
path.moveTo(eventX, eventY);
lastTouchX = eventX;
lastTouchY = eventY;
return true;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
resetDirtyRect(eventX, eventY);
int historySize = event.getHistorySize();
for (int i = 0; i < historySize; i++)
{
float historicalX = event.getHistoricalX(i);
float historicalY = event.getHistoricalY(i);
expandDirtyRect(historicalX, historicalY);
path.lineTo(historicalX, historicalY);
}
path.lineTo(eventX, eventY);
break;
default:
debug("Ignored touch event: " + event.toString());
return false;
}
invalidate((int) (dirtyRect.left - HALF_STROKE_WIDTH),
(int) (dirtyRect.top - HALF_STROKE_WIDTH),
(int) (dirtyRect.right + HALF_STROKE_WIDTH),
(int) (dirtyRect.bottom + HALF_STROKE_WIDTH));
lastTouchX = eventX;
lastTouchY = eventY;
return true;
}
private void debug(String string){
}
private void expandDirtyRect(float historicalX, float historicalY)
{
if (historicalX < dirtyRect.left)
{
dirtyRect.left = historicalX;
}
else if (historicalX > dirtyRect.right)
{
dirtyRect.right = historicalX;
}
if (historicalY < dirtyRect.top)
{
dirtyRect.top = historicalY;
}
else if (historicalY > dirtyRect.bottom)
{
dirtyRect.bottom = historicalY;
}
}
private void resetDirtyRect(float eventX, float eventY)
{
dirtyRect.left = Math.min(lastTouchX, eventX);
dirtyRect.right = Math.max(lastTouchX, eventX);
dirtyRect.top = Math.min(lastTouchY, eventY);
dirtyRect.bottom = Math.max(lastTouchY, eventY);
}
}
}
Please leave your comments and feedback if any.Thank you!!!
Thank you so much for sharing this worth able content with us. The concept taken here will be useful for my future programs and i will surely implement them in my study. Keep blogging article like this.
ReplyDeleteElectronic Signature Software