user2931394
user2931394

Reputation: 39

Getting Signature From the user as input in Android (Eclipse)

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

Answers (2)

Harshal Benake
Harshal Benake

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

FabianCook
FabianCook

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

Related Questions