Now flutter is very common in the mobile app development world. Every developer or even clients know about it and its power. In a very short time, spam flutter is on every developer’s mind. The result is awesome, developers are making very good plugins to make development easy, fast and up to the mark. Today in this flutter tutorial I am going to share a wonderful flutter example using a simple plugin which can make flutter signature pad in a few minutes with help of a few lines.
The name of the plugin is “signature” , which work pretty decent work. Let’s start learning how to make flutter signature pad to take any one’s signature or autograph depends upon the app you are making.
Adding Dependencies
dependencies:
signature: ^3.2.0
Installing It
$ flutter pub get
Finally, Import the plugin
import 'package:signature/signature.dart';
If you have already read my previous tutorials and posts, you were aware that I assume you have basic understanding of flutter development, widgets, state or stateless thing. So I no need to explain each and every step.
Output
To make flutter signature pad we need 2 main classes from “signature” plugin.
- SignatureController
- Signature
First of all need to make set SignatureController
final SignatureController _controller = SignatureController(
penStrokeWidth: 5, //you can set pen stroke with by changing this value
penColor: Colors.black, // change your pen color
exportBackgroundColor: Colors.white, //set the color you want to see in final result
);
and in our widgets hierarchy we need to user Signature
Signature(
controller: _controller,
height: 500, // whatever heigt is needed
backgroundColor: Colors.blueGrey.shade50, //set background color of your signature widget
),
These two tiny blocks of code are enough to make working signature pad. Now let’s get the signature from the program.
var data = await _controller.toPngBytes();
All done, you can show, save or do whatever you want to do with this returned data. Your flutter signature pad ready to take anyone’s signature.
Here is the complete flutter source code
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:signature/signature.dart';
import 'package:path_provider/path_provider.dart' as path_provider;
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String path = '/storage/emulated/0/flutterfumes';
final SignatureController _controller = SignatureController(
penStrokeWidth: 5,
penColor: Colors.black,
exportBackgroundColor: Colors.white,
);
@override
void initState() {
super.initState();
_controller.addListener(() => print("Value changed"));
}
Future<void> writeToFile(ByteData data, String path) {
final buffer = data.buffer;
return new File(path).writeAsBytes(
buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
}
Future<String> _createFile(var data) async {
Uint8List bytes = data;
final result = await ImageGallerySaver.saveImage(bytes);
print(result);
return result;
}
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Builder(
builder: (context) => Scaffold(
appBar: AppBar(title: Text('Signature Pad Example')),
body: ListView(
children: <Widget>[
Container(
height: 100,
child: Center(
child: Text('Draw You Signature'),
),
),
//SIGNATURE CANVAS
Signature(
controller: _controller,
height: 500,
backgroundColor: Colors.blueGrey.shade50,
),
//OK AND CLEAR BUTTONS
Container(
decoration: const BoxDecoration(color: Colors.black),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
//SHOW EXPORTED IMAGE IN NEW ROUTE
IconButton(
icon: const Icon(Icons.check),
color: Colors.blue,
onPressed: () async {
if (_controller.isNotEmpty) {
var data = await _controller.toPngBytes();
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: Container(
color: Colors.grey[300],
child: Image.memory(data))),
);
},
),
);
}
}),
//CLEAR CANVAS
IconButton(
icon: const Icon(Icons.clear),
color: Colors.blue,
onPressed: () {
setState(() => _controller.clear());
},
),
IconButton(
icon: const Icon(Icons.save),
color: Colors.blue,
onPressed: () async {
if (_controller.isNotEmpty) {
var data = await _controller.toPngBytes();
if (await Permission.storage.request().isGranted) {
// Either the permission was already granted before or the user just granted it.
await _createFile(data);
Fluttertoast.showToast(msg: 'Signature Saved...');
}
}
},
),
],
),
),
Container(
height: 300,
child: Center(
child: Text('Big container to test scrolling issues'),
),
),
],
),
),
),
);
}
}
I hope it will help you to learn, make and grow. If you have any question or query feel free to ask in comments.
You can also download source code
Hello, thank you very much for this Flutter Signature Pad tutorial, it was super helpful.
I have a few parts that got me a little confused though:
1- I see the “writeToFile” method at the top but I do not see it used anywhere else after its declaration.
2- A lot of variables were declared and named “data”, it was hard to tell which is which.
3- In the “createFile” method, how do I set the directory in the Internal Storage I want the image saved to?
Hello, I am glad to hear, you found it useful.
Regarding your questions
1. writeToFile method is the answer of your third question, means, you don’t need to use create file in case you want to save file at your preferred location. In write to file you have already file which have signature content, you need to use path_provider or path lib to get the path where you want to save.
2. You don’t need to bother about the data variable used multiple times, because it is local variable, you can give any name, but as your question concerned, data is local variable and have scope inside the method only, so all variable having same name but different methods treated as different variables in memory.
3. I think it is already cleared.
I hope it will help, leave a comment if you need any further help. Subscribe for more simple but useful Articles and tutorials.