Signature Pad Example
To create a Signature Pad in Android App
Step 1: Goto build.gradle[ Module:App]
Add the followings as shown in the picture below
repositories { mavenCentral() }
compile 'com.github.gcacace:signature-pad:1.2.1'
Set Permissions at AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.INTERNET" />
Step 2: Add the following to Strings.xml
<resources> <string name="app_name">SignaturePad</string> <string name="agreement">I agree to the terms and conditions.</string> <string name="clear_pad">Clear Pad</string> <string name="save_signature">Save Signature</string> </resources>
Step 3: create a Values XML file name as dimens.xml
Right clicked on App> New> XML > Values XML file
<?xml version="1.0" encoding="utf-8"?> <!-- Default screen margins, per the Android Design guidelines. --> <resources> <dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen> </resources>
Step 4: create a layout file for activity_main.xml
For a quick start, you may copy and paste the XML codes onto activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:signature="http://schemas.android.com/apk/res-auto" 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"> <RelativeLayout android:id="@+id/signature_pad_container" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_marginBottom="52dp"> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="100dp" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_below="@+id/signature_pad" android:text="Signature" android:textSize="36sp" /> <com.github.gcacace.signaturepad.views.SignaturePad android:id="@+id/signature_pad" android:layout_width="match_parent" android:layout_height="200dp" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentTop="true" /> </RelativeLayout> <LinearLayout android:id="@+id/buttons_container" android:paddingTop="16dp" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_alignParentBottom="true"> <Button android:id="@+id/clear_button" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="@string/clear_pad" android:enabled="false" /> <Button android:id="@+id/save_button" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="@string/save_signature" android:enabled="false" /> </LinearLayout> <TextView android:id="@+id/signature_pad_description" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/buttons_container" android:layout_centerHorizontal="true" android:text="@string/agreement" android:textColor="@android:color/darker_gray" /> </RelativeLayout>
For a quick start, you may copy and paste the java codes onto MainActivity.java
package signature.mdad.signaturepad; import android.Manifest; import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.Toast; import com.github.gcacace.signaturepad.views.SignaturePad; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; public class MainActivity extends Activity { private static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = {Manifest.permission.WRITE_EXTERNAL_STORAGE}; private SignaturePad mSignaturePad; private Button mClearButton; private Button mSaveButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); verifyStoragePermissions(this); setContentView(R.layout.activity_main); mSignaturePad = (SignaturePad) findViewById(R.id.signature_pad); mSignaturePad.setOnSignedListener(new SignaturePad.OnSignedListener() { @Override public void onStartSigning() { Toast.makeText(MainActivity.this, "OnStartSigning", Toast.LENGTH_SHORT).show(); } @Override public void onSigned() { mSaveButton.setEnabled(true); mClearButton.setEnabled(true); } @Override public void onClear() { mSaveButton.setEnabled(false); mClearButton.setEnabled(false); } }); mClearButton = (Button) findViewById(R.id.clear_button); mSaveButton = (Button) findViewById(R.id.save_button); mClearButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mSignaturePad.clear(); } }); mSaveButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Bitmap signatureBitmap = mSignaturePad.getSignatureBitmap(); if (addJpgSignatureToGallery(signatureBitmap)) { Toast.makeText(MainActivity.this, "Signature saved into the Gallery", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "Unable to store the signature", Toast.LENGTH_SHORT).show(); } if (addSvgSignatureToGallery(mSignaturePad.getSignatureSvg())) { Toast.makeText(MainActivity.this, "SVG Signature saved into the Gallery", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "Unable to store the SVG signature", Toast.LENGTH_SHORT).show(); } } }); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { switch (requestCode) { case REQUEST_EXTERNAL_STORAGE: { // If request is cancelled, the result arrays are empty. if (grantResults.length <= 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) { Toast.makeText(MainActivity.this, "Cannot write images to external storage", Toast.LENGTH_SHORT).show(); } } } } public File getAlbumStorageDir(String albumName) { // Get the directory for the user's public pictures directory. File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), albumName); if (!file.mkdirs()) { Log.e("SignaturePad", "Directory not created"); } return file; } public void saveBitmapToJPG(Bitmap bitmap, File photo) throws IOException { Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(newBitmap); canvas.drawColor(Color.WHITE); canvas.drawBitmap(bitmap, 0, 0, null); OutputStream stream = new FileOutputStream(photo); newBitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream); stream.close(); } public boolean addJpgSignatureToGallery(Bitmap signature) { boolean result = false; try { File photo = new File(getAlbumStorageDir("SignaturePad"), String.format("Signature_%d.jpg", System.currentTimeMillis())); saveBitmapToJPG(signature, photo); scanMediaFile(photo); result = true; } catch (IOException e) { e.printStackTrace(); } return result; } private void scanMediaFile(File photo) { Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); Uri contentUri = Uri.fromFile(photo); mediaScanIntent.setData(contentUri); MainActivity.this.sendBroadcast(mediaScanIntent); } public boolean addSvgSignatureToGallery(String signatureSvg) { boolean result = false; try { File svgFile = new File(getAlbumStorageDir("SignaturePad"), String.format("Signature_%d.svg", System.currentTimeMillis())); OutputStream stream = new FileOutputStream(svgFile); OutputStreamWriter writer = new OutputStreamWriter(stream); writer.write(signatureSvg); writer.close(); stream.flush(); stream.close(); scanMediaFile(svgFile); result = true; } catch (IOException e) { e.printStackTrace(); } return result; } /** * Checks if the app has permission to write to device storage * <p/> * If the app does not has permission then the user will be prompted to grant permissions * * @param activity the activity from which permissions are checked */ public static void verifyStoragePermissions(Activity activity) { // Check if we have write permission int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); if (permission != PackageManager.PERMISSION_GRANTED) { // We don't have permission so prompt the user ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE); } } }
Step 5: Build and Run the App