Akeng.SignaturePad
1.0.3
dotnet add package Akeng.SignaturePad --version 1.0.3
NuGet\Install-Package Akeng.SignaturePad -Version 1.0.3
<PackageReference Include="Akeng.SignaturePad" Version="1.0.3" />
<PackageVersion Include="Akeng.SignaturePad" Version="1.0.3" />
<PackageReference Include="Akeng.SignaturePad" />
paket add Akeng.SignaturePad --version 1.0.3
#r "nuget: Akeng.SignaturePad, 1.0.3"
#:package Akeng.SignaturePad@1.0.3
#addin nuget:?package=Akeng.SignaturePad&version=1.0.3
#tool nuget:?package=Akeng.SignaturePad&version=1.0.3
✍️ Akeng.SignaturePad
A modern, natural and MVVM-friendly signature pad for .NET MAUI.
Akeng.SignaturePad is an open-source signature capture control for .NET MAUI, designed for smooth handwritten input, natural ink rendering, persistence and high-quality image export.
Built for forms, approvals, inspections, deliveries, agreements, onboarding flows and business applications.
⭐ If you find the project useful, consider starring the repository.
✨ Features
- ✍️ Smooth handwritten signature capture
- 🖋️ Natural velocity-based dynamic ink
- 🎨 Uniform and variable-width strokes
- 🪄 Built-in ink presets:
Natural,Fine,Bold - 👆 Touch, mouse and basic stylus input
- ↩️ Undo / Redo / Clear
- ✅ Signature validation
- 🔎 Empty signature detection
- 🔒 Read-only mode
- 🧩 MVVM and two-way binding support
- 💾 Versioned JSON persistence
- 🖼️ PNG & JPEG export
- ✂️ Automatic whitespace trimming
- 🔍 High-resolution export
- 🌫️ Transparent PNG support
- 🌙 Dark mode friendly
- 📱 Android, iOS, Mac Catalyst and Windows
- 🚫 No platform-specific initialization required
📦 Installation
Install from NuGet:
dotnet add package Akeng.SignaturePad
Or search for:
Akeng.SignaturePad
in the Visual Studio NuGet Package Manager.
No additional configuration is required in MauiProgram.cs.
🚀 Quick Start
Add the namespace:
xmlns:signature="clr-namespace:AkengSignaturePad.Controls;assembly=AkengSignaturePad"
Then add the control:
<signature:SignaturePadView
x:Name="SignaturePad"
HeightRequest="240" />
That's it.
🖋️ Natural Ink
Akeng.SignaturePad supports velocity-aware ink rendering.
Instead of rendering every stroke with a constant width, the control can dynamically adapt stroke thickness based on drawing speed.
For the recommended natural handwriting experience:
<signature:SignaturePadView
HeightRequest="240"
InkPreset="Natural"
HintText="Sign here" />
Available presets:
| Preset | Description |
|---|---|
Custom |
Full manual configuration |
Natural |
Balanced handwriting experience |
Fine |
Thin and precise ink |
Bold |
Stronger and thicker strokes |
Custom Dynamic Ink
For complete control:
<signature:SignaturePadView
HeightRequest="240"
StrokeStyle="Velocity"
MinimumStrokeWidth="1.0"
MaximumStrokeWidth="4.5"
VelocitySensitivity="1.0"
MinimumPointDistance="1.2" />
Available stroke styles:
SignatureStrokeStyle.Uniform
SignatureStrokeStyle.Velocity
Uniform remains the default for backward compatibility.
🎨 Customization
<signature:SignaturePadView
x:Name="SignaturePad"
HeightRequest="260"
InkPreset="Natural"
StrokeColor="#111827"
SignatureBackgroundColor="White"
BorderColor="#E5E7EB"
BorderThickness="1"
CornerRadius="16"
ShowSignatureLine="True"
SignatureLineColor="#D1D5DB"
ShowHint="True"
HintText="Sign here"
HintTextColor="#9CA3AF"
MinimumStrokeLength="40"
MinimumStrokeCount="1" />
↩️ Undo, Redo & Clear
SignaturePad.Undo();
SignaturePad.Redo();
SignaturePad.Clear();
State is exposed directly:
SignaturePad.CanUndo;
SignaturePad.CanRedo;
SignaturePad.IsEmpty;
SignaturePad.IsValid;
This also makes the control easy to integrate with MVVM.
✅ Signature Validation
A tap or extremely small stroke should not necessarily be considered a valid signature.
Configure basic validation directly in XAML:
<signature:SignaturePadView
MinimumStrokeLength="40"
MinimumStrokeCount="1" />
Then:
if (!SignaturePad.Validate())
{
await DisplayAlert(
"Signature required",
"Please provide a valid signature.",
"OK");
return;
}
Validation checks whether sufficient drawing input has been provided. It is not biometric signature verification.
🧬 SignatureData
Akeng.SignaturePad does not treat a signature as only an image.
The original drawing data can be retrieved using:
SignatureData signature =
SignaturePad.GetSignatureData();
The model contains the original strokes and points:
SignatureData
├── Width
├── Height
├── CreatedAt
│
└── Strokes
├── Color
├── Width
│
└── Points
├── X
├── Y
├── Timestamp
└── Width
Each point can preserve its own stroke width, allowing dynamic ink signatures to be stored and rendered again later.
💾 JSON Persistence
Serialize the current signature:
string json =
SignaturePad.GetSignatureJson();
Restore it later:
SignaturePad.LoadJson(json);
Serialization can also be used independently from the control:
var json =
SignatureSerializer.Serialize(signature);
var restored =
SignatureSerializer.Deserialize(json);
The JSON format is versioned to support future evolution of the signature model.
🔄 Load an Existing Signature
SignaturePad.LoadSignatureData(signature);
This is useful for:
- restoring forms
- displaying saved signatures
- editing captured signatures
- confirmation screens
- approval workflows
For display-only scenarios:
<signature:SignaturePadView
Signature="{Binding Signature}"
IsReadOnly="True" />
🖼️ Image Export
Export as bytes:
byte[] bytes =
await SignaturePad.GetImageBytesAsync();
Or as a stream:
await using var stream =
await SignaturePad.GetImageStreamAsync();
Advanced Export
var bytes =
await SignaturePad.GetImageBytesAsync(
new SignatureExportOptions
{
Format = SignatureImageFormat.Png,
Scale = 2f,
TrimWhitespace = true,
Padding = 16f,
BackgroundColor = Colors.White
});
Available options:
| Property | Description |
|---|---|
Format |
PNG or JPEG |
Scale |
Output resolution multiplier |
TrimWhitespace |
Removes unused space |
Padding |
Adds padding around the signature |
BackgroundColor |
Export background color |
For transparent PNG:
var options =
new SignatureExportOptions
{
Format = SignatureImageFormat.Png,
BackgroundColor = null
};
🧩 MVVM
Bind the signature directly to your ViewModel:
<signature:SignaturePadView
Signature="{Binding Signature, Mode=TwoWay}"
IsValid="{Binding IsSignatureValid}"
SignatureCompletedCommand="{Binding SignatureCompletedCommand}" />
Using CommunityToolkit.Mvvm:
[ObservableProperty]
private SignatureData? signature;
[ObservableProperty]
private bool isSignatureValid;
[RelayCommand]
private void SignatureCompleted(
SignatureData signature)
{
// Save or process the signature.
}
Your ViewModel does not need a reference to SignaturePadView.
⚡ Events
Available events:
SignatureStarted
SignatureChanged
SignatureCompleted
Cleared
Example:
private void OnSignatureCompleted(
object? sender,
SignatureCompletedEventArgs e)
{
if (!e.IsValid)
return;
var signature = e.Signature;
// Continue workflow...
}
🌙 Dark Mode
Standard .NET MAUI theme bindings are supported:
<signature:SignaturePadView
StrokeColor="{AppThemeBinding
Light=#111827,
Dark=White}"
SignatureBackgroundColor="{AppThemeBinding
Light=White,
Dark=#111827}"
BorderColor="{AppThemeBinding
Light=#E5E7EB,
Dark=#374151}" />
📚 Core API
Drawing
| Property | Default |
|---|---|
StrokeColor |
#111827 |
StrokeWidth |
2.5 |
StrokeStyle |
Uniform |
InkPreset |
Custom |
MinimumStrokeWidth |
1.1 |
MaximumStrokeWidth |
4.2 |
VelocitySensitivity |
1.0 |
MinimumPointDistance |
1.5 |
State & Validation
| Property | Description |
|---|---|
Signature |
Current SignatureData |
IsEmpty |
Indicates whether the pad is empty |
IsValid |
Current validation state |
CanUndo |
Undo availability |
CanRedo |
Redo availability |
IsReadOnly |
Prevents signature modification |
MinimumStrokeLength |
Minimum valid drawing length |
MinimumStrokeCount |
Minimum number of valid strokes |
Main Methods
| Method | Description |
|---|---|
Clear() |
Clears the signature |
Undo() |
Removes the latest stroke |
Redo() |
Restores the latest undone stroke |
Validate() |
Validates the signature |
GetSignatureData() |
Gets vector signature data |
LoadSignatureData() |
Loads signature data |
GetSignatureJson() |
Serializes the signature |
LoadJson() |
Restores JSON signature data |
GetImageStreamAsync() |
Exports to an image stream |
GetImageBytesAsync() |
Exports to a byte array |
📱 Supported Platforms
| Platform | Status |
|---|---|
| Android | ✅ |
| iOS | ✅ |
| Mac Catalyst | ✅ |
| Windows | ✅ |
The core drawing engine is based on .NET MAUI graphics APIs and requires no platform-specific initialization.
🗺️ Roadmap
v1.0 — Foundation ✅
Signature capture, Undo/Redo, validation, MVVM, SignatureData, JSON persistence, PNG/JPEG export, read-only mode and appearance customization.
v1.1 — Natural Ink 🚧
- Velocity-based strokes
- Variable stroke width
- Velocity smoothing
- Variable-width rendering
- Natural / Fine / Bold presets
- Additional ink tuning
Next
- SVG vector export
- Coordinate normalization
- Signature resize modes
- Base64 helpers
- Full-screen capture
- Advanced validation
- Signature playback
- Pressure-sensitive stylus input
- Apple Pencil improvements
- Surface Pen improvements
- Palm rejection
- Signature metadata
- Integrity / hash helpers
- Accessibility improvements
The roadmap evolves based on community feedback and real-world usage.
🔐 Security & Legal Notice
Akeng.SignaturePad captures handwritten signature input.
It does not provide identity verification, biometric verification, digital certificates, qualified electronic signatures or legal signature certification.
Legal validity depends on the application, jurisdiction, identity verification process, document integrity, audit trail and surrounding business workflow.
🤝 Contributing
Contributions, bug reports, ideas and feature requests are welcome.
When reporting an issue, please include:
- Platform
- .NET / .NET MAUI version
- Akeng.SignaturePad version
- Reproduction steps
- Expected behavior
- Actual behavior
❤️ Akeng
Akeng.SignaturePad is part of a growing collection of lightweight, developer-friendly controls for .NET MAUI.
Build less boilerplate. Focus on your application.
Made with ❤️ by Dr. Ange Gabriel Belinga using .NET MAUI.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net8.0-windows10.0.19041 is compatible. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net9.0-windows10.0.19041 is compatible. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Microsoft.Maui.Controls (>= 8.0.100)
- Microsoft.Maui.Graphics.Skia (>= 9.0.0-rc.1.24453.9)
-
net8.0-windows10.0.19041
- Microsoft.Maui.Controls (>= 8.0.100)
- Microsoft.Maui.Graphics.Skia (>= 9.0.0-rc.1.24453.9)
-
net9.0
- Microsoft.Maui.Controls (>= 9.0.111)
- Microsoft.Maui.Graphics.Skia (>= 9.0.0-rc.1.24453.9)
-
net9.0-windows10.0.19041
- Microsoft.Maui.Controls (>= 9.0.111)
- Microsoft.Maui.Graphics.Skia (>= 9.0.0-rc.1.24453.9)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.