Android Tutorial Signature Capture Tutorial

Status
Not open for further replies.
Several developers were interested in adding support for signature capturing in their Android application.
The attached code module makes it easy to capture the signature and save it to a file.

signaturecapture_1.png


You should create a layout similar to the above layout.
The drawing is done on a Panel view.

Load the layout (or create it programmatically), initialize the canvas object which does the actual drawing and initialize the SignatureData object:
B4X:
Sub Globals
    Dim Panel1 As Panel
    Dim Canvas1 As Canvas
    Dim SD As SignatureData 'This object holds the data required for SignatureCapture
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("1")
    Canvas1.Initialize(Panel1)
    SD.Initialize
    SD.Canvas = Canvas1
    SD.Panel = Panel1
    SD.SignatureColor = Colors.Black
    SD.SignatureWidth = 5dip 'Stroke width
End Sub
Add events for the panel Touch event and for the buttons. These events call the SignatureCapture module.
B4X:
Sub Panel1_Touch (Action As Int, X As Float, Y As Float)
    SignatureCapture.Panel_Touch(SD, x, y, Action)
End Sub
Sub btnSave_Click
    SignatureCapture.Save(SD, File.DirRootExternal, "sign.png")
    ToastMessageShow("Signature saved to: " & File.Combine(File.DirRootExternal, "sign.png"), True)
End Sub
Sub btnClear_Click
    SignatureCapture.Clear(SD)
End Sub
That's it.
 

Attachments

  • SignatureCapture.zip
    6.4 KB · Views: 4,037

Arf

Well-Known Member
Licensed User
Longtime User
Hi guys,
I basically copy and pasted code out this tutorial into my project, renamed SignatureCapture to WaveFormCapture and did a few other renames.
I'm getting a error "object reference not set to instance of object" for the following line:
WD.Canvas = Canvas1

B4X:
Sub Globals
    Private btnStart As Button
    Dim Timer2 As Timer
    Dim Canvas1 As Canvas
    Dim Waveform As Panel
    Dim WD As WaveFormData
    Private GraphView As ImageView
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("2")
    Canvas1.Initialize(Waveform)

    WD.Initialize
    WD.Canvas = Canvas1
    WD.Panel = Waveform
    WD.SignatureColor = Colors.Black
    WD.SignatureWidth = 2dip 'Stroke width
    Timer2.Initialize("Timer2", 200)
    Timer2.Enabled = True
End Sub
and
B4X:
'Code module
Sub Process_Globals
    Dim px, py As Int
    Type WaveFormData (Canvas As Canvas, Panel As Panel, WaveFormColor As Int, WaveFormWidth As Int)
End Sub

Sub Panel_Touch(WD As WaveFormData, x As Int,y As Int, Action As Int)
    If Action = 0 Then 'mouse down constant
        px = x
        py = y
    Else
        WD.Canvas.DrawLine(px, py, x, y, WD.WaveFormColor, WD.WaveFormWidth)
        WD.Panel.Invalidate
        px = x
        py = y
    End If
End Sub

I'm probably missing something really simple but can't see it.
 

klaus

Expert
Licensed User
Longtime User
There is a problem in your code but I'm not sure if this raises the error you mention.
You define the type with Type WaveFormData (CanvasAsCanvas, PanelAsPanel, WaveFormColor AsInt, WaveFormWidth AsInt)
Then you use:
WD.SignatureColor = Colors.Black
WD.SignatureWidth = 2dip 'Stroke width

here you use the original names !?
 

Arf

Well-Known Member
Licensed User
Longtime User
A further question: I create a Panel on top of a bitmap (in a ImageView) that has graph axes and all sorts of stuff on it.
My Panel is positioned on top of the bitmap, is sized to cover the whole graph area, and Alpha set to zero in the designer, so I can see the underlying bitmap through it.
I then draw a waveform using the same technique as used in the signature capture tutorial, which works fine.
Now I'm trying to clear the drawn bits to expose the underlying bitmap, if I use the tutorial code, the panel is filled with a color (as expected).
If I change the fill color to be ARGB with alpha set to zero, the fill has no effect.
Is there any way I can clear this panel, or would I need to clear it be drawing a bitmap to it (which exactly matched the underlying bitmap)?
 

Arf

Well-Known Member
Licensed User
Longtime User
I'm using this code as abasis for drawing graphs for the app I'm making, I've tried to speed it up by only invalidating the area that has a new line being drawn to it, so:
The old:
WD.Canvas.DrawLine(px, py, x, y, WD.WaveFormColor, WD.WaveFormWidth)
WD.Panel.Invalidate

The new:
WD.Canvas.DrawLine(px, py, x, y, WD.WaveFormColor, WD.WaveFormWidth)
WD.Panel.Invalidate3(px,py,x,y)

Can't really tell if it's working but I guess it must be, the graphs draw fine. My question is, does it matter is px or py are actually smaller then x and y?
The arguments are supposed to be (Left, Top, Right, Bottom), but when my graph is on it's way back home I'm going to end up sending (Right, Bottom, Left, Top) instead. Should I do a check and re-arrange arguments accordingly, or is there no effect?
 

Arf

Well-Known Member
Licensed User
Longtime User
Oops, answered my own question.. The change I made was to the signature drawing function, didn't realise I had left that in there, I copied and modified that Sub to create my graph drawing one.

The answer to the question is yes, they need to conform to LTRB. I did sorted that then still has a oddly drawn graph, realised that it was because the line thickness is more than 1, so I tried to invalidate the l-2,t-2,r+2,b+2 area instead and that works fine.
 

klaus

Expert
Licensed User
Longtime User
If you reall want to use the surrounding rectangle you could use:
B4X:
WD.Panel.Invalidate3(Min(px, x) - WD.WaveFormWidth / 2, Min(py, y) - WD.WaveFormWidth / 2, Abs(px - x) + WD.WaveFormWidth, Abs(py - y) + WD.WaveFormWidth)
I'm not convinced that it will increase the update.
 

udg

Expert
Licensed User
Longtime User
Hi all,

may I ask your advice on using this module for a specific project I was asked to develop?
An employer wishes to use a tablet to record each day how many hours each member of its staff worked on its premise along with the worker's signature as acceptance evidence.
It seems that graphically this module solves the collecting part of the specs.

Now, for the recording (to an external SQL DB) part. What do you suggest I record along with time data?
The whole signature picture? As a file (as I feel right) or as BLOB?
Or is it better to record points making the picture as read a few posts above? In this latter case will it be easy to go from point list to signature drawing again?

TIA

Umberto
 

Peter Simpson

Expert
Licensed User
Longtime User
Good morning all,
@Erel or @klaus or @thedesolatesoul or anybody really.

This original code works great, especially if you add Anti Alias to make the lines smoother. My question is this, is there anyway to speed up the point to point plotting, thus making curves smoother in signatures.

When my clients customers sign really fast, it does not look that smooth. I suggested that he gets a Nexus 5 which he did and it did make things slightly better(previously they were using really slow cheap devices), but they are still moaning. I've also suggested that he tells his own customers to sign slower, but he point blank refuses to tell his customers how to sign their signature(he really is an idiot). He has downloaded apps like Digital signature creator, Signature saver, Signature capture etc to prove to me that it can be done, idiot. As I've built the signature feature into their Android courier collection/delivery app, I was wondering does anybody know how these other app get dead smooth signatures.

I'm more than happy with the results using the code in this post, especially with Anti Alias. But my client is being a perfectionist which is seriously annoying :mad:

Thank you...
 
Last edited:

thedesolatesoul

Expert
Licensed User
Longtime User
Good morning all,
@Erel or @klaus or @thedesolatesoul or anybody really.

This original code works great, especially if you add Anti Alias to make the lines smoother. My question is this, is there anyway to speed up the point to point plotting, thus making curves smoother in signatures.

When my clients customers sign really fast, it does not look that smooth. I suggested that he gets a Nexus 5 which he did and it did make things slightly better(previously they were using really slow cheap devices), but they are still moaning. I've also suggested that he tells his own customers to sign slower, but he point blank refuses to tell his customers how to sign their signature(he really is an idiot). He has downloaded apps like Digital signature creator, Signature saver, Signature capture etc to prove to me that it can be done, idiot. As I've built the signature feature into their Android courier collection/delivery app, I was wondering does anybody know how these other app get dead smooth signatures.

I'm more than happy with the results using the code in this post, especially with Anti Alias. But my client is being a perfectionist which is seriously annoying :mad:

Thank you...
The code for plotting the signature is working as fast as possible. There is no delay at all.
However, since you have so many points, it will be more jaggedy (if that was a word!).
So what you want is smoother curves?
 

Peter Simpson

Expert
Licensed User
Longtime User

Beja

Expert
Licensed User
Longtime User
Hi Erel and all,

The png file is always being saved with the same name.. overriding the precious one.
How can I name it, or at least the app can increment the a last digit, e.g. sign0.png, sign1.png, sign2.png... (starting from the last name digit on device)

Thanks in advance
 
Status
Not open for further replies.
Top