Reputation: 39
I am developing an android application, in this one page after filling up the details, at the end of the page i need to place some imageview or fragement in which user can able to sign thier signature it by touching. so that i can save that signature as image while clicking submit.
i have googled about this but i did not get any tutorial kind of thing to start. Please help me out from this or share some link if you guys know.
Thanks in Advance, Srikanth A this is my class file,
package com.example.test_signature;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable.Callback;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
public class SignatureView extends SurfaceView implements OnTouchListener, Callback, android.view.SurfaceHolder.Callback {
public SignatureView(Context context) {
super(context);
init();
}
public SignatureView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
this.setBackgroundColor(Color.WHITE);
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(3);
this.setOnTouchListener(this);
this.getHolder().addCallback(this);
}
public void setStrokeWidth(float width){
mPaint.setStrokeWidth(width);
this.invalidate();
}
public void setColor(int color){
mPaint.setColor(color);
this.invalidate();
}
public void clear(){
mDots = new ArrayList<List<Dot>>();
//To prevent an exception
mDots.add(new ArrayList<Dot>());
this.invalidate();
}
private List<List<Dot>> mDots = new ArrayList<List<Dot>>();
private class Dot{
public float X = 0;
public float Y = 0;
public Dot(float x, float y){
X = x;
Y = y;
}
}
@Override
public boolean onTouch(View view, MotionEvent event) {
//mLastActivity = Calendar.getInstance();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
mDots.add(new ArrayList<Dot>());
mDots.get(mDots.size() - 1).add(new Dot(event.getX(), event.getY()));
this.invalidate();
break;
case MotionEvent.ACTION_UP:
mDots.get(mDots.size() - 1).add(new Dot(event.getX(), event.getY()));
this.invalidate();
break;
case MotionEvent.ACTION_MOVE:
mDots.get(mDots.size() - 1).add(new Dot(event.getX(), event.getY()));
this.invalidate();
break;
}
return true;
}
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
public void surfaceCreated(SurfaceHolder arg0) {
}
public void surfaceDestroyed(SurfaceHolder arg0) {
}
public Paint mPaint;
@Override
protected void onDraw(Canvas canvas) {
for(List<Dot> dots : mDots){
for(int i = 0; i < dots.size(); i++){
if(i - 1 == -1)
continue;
canvas.drawLine(dots.get(i - 1).X, dots.get(i - 1).Y, dots.get(i).X, dots.get(i).Y, mPaint);
}
}
}
public Bitmap getBitmap(){
Bitmap b = Bitmap.createBitmap(this.getWidth(), this.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
this.draw(c);
return b;
}
public boolean exportFile(String pathString, String fileString){
File path = new File(pathString);
path.mkdirs();
if(!fileString.toLowerCase(Locale.ENGLISH).contains(".png")){
fileString += ".png";
}
File file = new File(path, fileString);
FileOutputStream out;
try {
out = new FileOutputStream(file);
this.getBitmap().compress(Bitmap.CompressFormat.PNG, 90, out);
return true;
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
}
this is My XML file in which i have created the view for the user to put a signature.
<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=".SignatureView" >
<View
android:id="@+id/id"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<com.example.test_signature.SignatureView
android:id="@+id/signature"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:height="18dp"
android:width="18dp" />
</RelativeLayout>
i have created this sample to test the signature functionality. But whenever i run this code, my application get crashes. Anyone please help me out. I think i have done a mistake in my XML.
@FabianCook : pla look out the code i have pasted. I'hv followed your procedure oly. but can u pls tel me wats the problem in the code ?
I have edited my XML file as you suggested, but still my application getting crashes whenever i open.
<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=".SignatureView" >
<View
android:id="@+id/id"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.example.test_signature.SignatureView
android:id="@+id/signature"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>
Upvotes: 1
Views: 2353
Reputation: 2401
hope this code helps you:)
esign_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<android.gesture.GestureOverlayView
android:id="@+id/signaturePad"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="5"
android:background="@android:color/white"
android:clickable="false"
android:eventsInterceptionEnabled="true"
android:fadeEnabled="false"
android:gestureColor="#0000ff"
android:gestureStrokeLengthThreshold="0.1"
android:gestureStrokeType="multiple"
android:longClickable="false"
android:orientation="vertical"
android:uncertainGestureColor="#000000"
android:splitMotionEvents="true"
android:fadeOffset="10000000">
</android.gesture.GestureOverlayView>
<RelativeLayout
android:id="@+id/rellay_esign_donebutton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
>
<Button
android:id="@+id/DoneButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Done" />
<Button
android:id="@+id/ClearButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Clear" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
Esignature.java
public class Esignature extends Activity {
GestureOverlayView gestureView;
String path;
File file;
Bitmap bitmap;
public boolean gestureTouch=false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.esign_main);
Button donebutton = (Button) findViewById(R.id.DoneButton);
donebutton.setText("Done");
Button clearButton = (Button) findViewById(R.id.ClearButton);
clearButton.setText("Clear");
path=Environment.getExternalStorageDirectory()+"/signature.png";
file = new File(path);
file.delete();
gestureView = (GestureOverlayView) findViewById(R.id.signaturePad);
gestureView.setDrawingCacheEnabled(true);
gestureView.setAlwaysDrawnWithCacheEnabled(true);
gestureView.setHapticFeedbackEnabled(false);
gestureView.cancelLongPress();
gestureView.cancelClearAnimation();
gestureView.addOnGestureListener(new OnGestureListener() {
@Override
public void onGesture(GestureOverlayView arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
}
@Override
public void onGestureCancelled(GestureOverlayView arg0,
MotionEvent arg1) {
// TODO Auto-generated method stub
}
@Override
public void onGestureEnded(GestureOverlayView arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
}
@Override
public void onGestureStarted(GestureOverlayView arg0,
MotionEvent arg1) {
// TODO Auto-generated method stub
if (arg1.getAction()==MotionEvent.ACTION_MOVE){
gestureTouch=false;
}
else
{
gestureTouch=true;
}
}});
donebutton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
bitmap = Bitmap.createBitmap(gestureView.getDrawingCache());
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
fos = new FileOutputStream(file);
// compress to specified format (PNG), quality - which is
// ignored for PNG, and out stream
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
if(gestureTouch==false)
{
setResult(0);
finish();
}
else
{
setResult(1);
finish();
}
}
});
clearButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
gestureView.invalidate();
gestureView.clear(true);
gestureView.clearAnimation();
gestureView.cancelClearAnimation();
}
});
}
}
Upvotes: 1
Reputation: 20587
public class SignatureView extends SurfaceView implements OnTouchListener, Callback {
public SignatureView(Context context) {
super(context);
init();
}
public SignatureView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
this.setBackgroundColor(Color.WHITE);
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(3);
this.setOnTouchListener(this);
this.getHolder().addCallback(this);
}
public void setStrokeWidth(float width){
mPaint.setStrokeWidth(width);
this.invalidate();
}
public void setColor(int color){
mPaint.setColor(color);
this.invalidate();
}
public void clear(){
mDots = new ArrayList<List<Dot>>();
//To prevent an exception
mDots.add(new ArrayList<Dot>());
this.invalidate();
}
private List<List<Dot>> mDots = new ArrayList<List<Dot>>();
private class Dot{
public float X = 0;
public float Y = 0;
public Dot(float x, float y){
X = x;
Y = y;
}
}
@Override
public boolean onTouch(View view, MotionEvent event) {
//mLastActivity = Calendar.getInstance();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
mDots.add(new ArrayList<Dot>());
mDots.get(mDots.size() - 1).add(new Dot(event.getX(), event.getY()));
this.invalidate();
break;
case MotionEvent.ACTION_UP:
mDots.get(mDots.size() - 1).add(new Dot(event.getX(), event.getY()));
this.invalidate();
break;
case MotionEvent.ACTION_MOVE:
mDots.get(mDots.size() - 1).add(new Dot(event.getX(), event.getY()));
this.invalidate();
break;
}
return true;
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
@Override
public void surfaceCreated(SurfaceHolder arg0) {
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
}
public Paint mPaint;
@Override
protected void onDraw(Canvas canvas) {
for(List<Dot> dots : mDots){
for(int i = 0; i < dots.size(); i++){
if(i - 1 == -1)
continue;
canvas.drawLine(dots.get(i - 1).X, dots.get(i - 1).Y, dots.get(i).X, dots.get(i).Y, mPaint);
}
}
}
public Bitmap getBitmap(){
Bitmap b = Bitmap.createBitmap(this.getWidth(), this.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
this.draw(c);
return b;
}
public boolean exportFile(String pathString, String fileString){
File path = new File(pathString);
path.mkdirs();
if(!fileString.toLowerCase(Locale.ENGLISH).contains(".png")){
fileString += ".png";
}
File file = new File(path, fileString);
FileOutputStream out;
try {
out = new FileOutputStream(file);
this.getBitmap().compress(Bitmap.CompressFormat.PNG, 90, out);
return true;
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
}
I think the code explains its self
This code takes care of everything. Has some nice little functions for different things like saving the image to a file etc.
Place this in one of your packages, and then in your XML file replace
<View android:id="@+id/id"/>
with
<package.name.SignatureView android:id="@+id/id"/>
USAGE
Create a new class in your package called SignatureView
, delete everything in this file except for the first line, you should be left with package your.package.name
On the third line paste the code above and press Ctrl-Shift-O
and it will import everything you need.
Save this file and then build your project.
In your XML file use:
<your.package.name.SignatureView
android:id="@+id/signature"
android:width="match_parent"
android:height="match_parent"/>
Save this and build your project.
In your activity you can use:
SignatureView mSignature;
mSignature = (SignatureView) this.findViewById(R.id.signature);
And then access the functions you need to save the signature to a file:
mSignature.exportFile("/mnt/sdcard/", "signaturefile.png");
Upvotes: 5