Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Capturing Signatures on Android Devices (MonoForAndroid)

DZone's Guide to

Capturing Signatures on Android Devices (MonoForAndroid)

· Java Zone
Free Resource

Download Microservices for Java Developers: A hands-on introduction to frameworks and containers. Brought to you in partnership with Red Hat.

In a previous post I showed how to capture a signature on iOS devices. This post demos the same feature on Android using MonoDroid. The idea is to allow users to use their fingers or a stylus to enter a signature on the Screen. This signature could then be stored or sent to the server for further processing and data management. 

using System;
using Android.Content;
using Android.Graphics;
using Android.Views;




namespace MyApp.Views
{
	public class CaptureSignatureView : View
	{
		public CaptureSignatureView(Context c, SignatureData signatureData) : base(c)
		{
			SignatureData = signatureData;
			_Path = new Path();
			_BitmapPaint = new Paint(PaintFlags.Dither);
			_paint = new Paint
			{
				AntiAlias = true,
				Dither = true,
				Color = Color.Argb(255, 0, 0, 0)
			};
			_paint.SetStyle(Paint.Style.Stroke);
			_paint.StrokeJoin = Paint.Join.Round;
			_paint.StrokeCap = Paint.Cap.Round;
			_paint.StrokeWidth = 8;
		}




		protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
		{
			base.OnSizeChanged(w, h, oldw, oldh);
			_Bitmap = Bitmap.CreateBitmap(w, (h > 0 ? h : ((View)this.Parent).Height), Bitmap.Config.Argb8888);
			_Canvas = new Canvas(_Bitmap);
		}




		protected override void OnDraw(Canvas canvas)
		{
			canvas.DrawColor(Color.White);
			canvas.DrawBitmap(_Bitmap, 0, 0, _BitmapPaint);
			canvas.DrawPath(_Path, _paint);
		}




		private float _mX, _mY;
		private const float TouchTolerance = 4;




		private void TouchStart(float x, float y)
		{
			_Path.Reset();
			_Path.MoveTo(x, y);
			_mX = x;
			_mY = y;
			SignatureData.AddPoint(SignatureState.Start, (int)x, (int)y);
		}




		private void TouchMove(float x, float y)
		{
			float dx = Math.Abs(x - _mX);
			float dy = Math.Abs(y - _mY);




			if (dx >= TouchTolerance || dy >= TouchTolerance)
			{
				_Path.QuadTo(_mX, _mY, (x + _mX) / 2, (y + _mY) / 2);
				SignatureData.AddPoint(SignatureState.Move, (int)x, (int)y);
				_mX = x;
				_mY = y;
			}
		}




		private void TouchUp()
		{
			if (!_Path.IsEmpty)
			{
				_Path.LineTo(_mX, _mY);
				_Canvas.DrawPath(_Path, _paint);
			}
			else
			{
				_Canvas.DrawPoint(_mX, _mY, _paint);
			}
			SignatureData.AddPoint(SignatureState.End, (int)_mX, (int)_mY);




			_Path.Reset();
		}




		public override bool OnTouchEvent(MotionEvent e)
		{
			var x = e.GetX();
			var y = e.GetY();




			switch (e.Action)
			{
				case MotionEventActions.Down:
					TouchStart(x, y);
					Invalidate();
					break;
				case MotionEventActions.Move:
					TouchMove(x, y);
					Invalidate();
					break;
				case MotionEventActions.Up:
					TouchUp();
					Invalidate();
					break;
			}
			return true;
		}




		public void ClearCanvas()
		{
			_Canvas.DrawColor(Color.White);
			Invalidate();
		}




		public Bitmap CanvasBitmap()
		{
			return _Bitmap;
		}




		public void Clear()
		{
			ClearCanvas();
			SignatureData = new SignatureData();
		}




		#region Implementation




		private Bitmap _Bitmap;
		private Canvas _Canvas;
		private readonly Path _Path;
		private readonly Paint _BitmapPaint;
		private readonly Paint _paint;
		public  SignatureData SignatureData;




		#endregion
	}




}

The view above can be used to capture signature on Android devices using MonoForAndroid. Basically we catch all major touch events on the view (TouchStart, Move, and TouchEnd). With each touch we force a redraw of the view to update the drawing of the signature on the screen. At the end of the capturing of the Signature, we can have two ways of capturing (keeping) this signature. We could use the object _bitmap, which will have the image of the view, OR we could just capture all the coordinates of all the points send it to the server and reconstruct the signature (This is the option that I use). The second option gives more control on how to reconstruct the signature and how to use it. It also gives the ability to add Watermarks, change size and type of image and more.

The SignatureData class can be seen below holds a two dimensional array of all the points (moves) that compose the whole signature.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;




namespace MyApp.Classes
{
	public enum SignatureState
	{
		Start,
		Move,
		End
	}




	public class SignatureData
	{
		public List
	
 
  > Paths { get { return _Paths; } }
		public event EventHandler PointAdded;




		public Point LastPoint()
		{
			if (currentPath != null && currentPath.Count > 0)
			{
				return currentPath.Last();
			}
			return new Point(0, 0);
		}




		public void Clear()
		{
			_Paths = new List
	
  
   >();
			currentPath = new List

   
    ();
		}




		public void AddPoint(SignatureState state, int x, int y)
		{
			if (state == SignatureState.Start)
			{
				currentPath = new List

    
     ();
			}
			if (x != 0 && y != 0)
			{
				currentPath.Add(new Point(x, y));
			}
			if (state == SignatureState.End)
			{
				if (currentPath != null)
				{
					_Paths.Add(currentPath);
				}
			}
			OnPointAdded(EventArgs.Empty);
		}




		public int Length
		{
			get { return _Paths.Count; }
		}




		#region Implementation




		protected void OnPointAdded(EventArgs e)
		{
			if (PointAdded != null)
			{
				PointAdded(this, e);
			}
		}




		private List

     
       currentPath = new List

      
       ();
		private List
	
       
        > _Paths = new List
	
        
         >();




		#endregion




	}
}

        
       
      
     
    
   
  
 

In the next post, I will show how to capture the signature as a list of points to use it on the server to redraw the signature. Meanwhile, feel free to reuse this code and shot me any comments or suggestions that you might have

Download Building Reactive Microservices in Java: Asynchronous and Event-Based Application Design. Brought to you in partnership with Red Hat

Topics:

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}