Introdução
Eai, clan. Tudo certo com vocês?
Hoje quero explicar como que eu fiz pra criar um campo de assinatura manual utilizando Flutter.
Estamos acostumados a utilizar assinatura digital para assinar documentos, mas existem alguns casos que ainda utilizam este tipo de assinatura. Mas a intenção deste post é para mostrar como você pode estar criando um campo onde pode ser rabiscado. Haha'
Então vamos partir do principio que temos que fazer uma assinatura em um determinado campo.
Separei em dois modos
Eu acho muito importante nós utilizarmos algo que já tenha pronto, para não ficar reinventando a roda. Então eu separei em duas partes de como fazer este campo.
A primeira maneira é utilizar um plugin Signature que esta disponível no pub.dev. É bem rápido e simples de utilizar.
Segunda é montar esse campo utilizando CustomPainter do Flutter, é um pouco mais trabalhoso criar só que você consegue adicionar coisas mais especificas.
Utilizando Plugin Signature
Primeiro vai instanciar um controlador com as suas configurações de desenho. Por exemplo:
final SignatureController _controller = SignatureController(
penStrokeWidth: 4,
penColor: Colors.black,
exportBackgroundColor: Colors.transparent,
);
Neste controlador coloquei uma espessura de 4, cor preta e um fundo transparente.
Próximo passa é passar este controlador para o Signature onde vamos assinar ou desenhar.
Signature(
controller: widget._controller,
height: 600,
backgroundColor: Colors.transparent,
)
Depois de assinar você pode pegar os bytes em png do controlador e transformar isso em uma imagem.
Image.memory(_controller.toPngBytes())
Utilizando o Widget CustomPainter
Eu separei cada parte em uma classe que eu criei, você pode conferir o código completo no repositório do Git Hub. Link no final do artigo.
Paint e Offset
Paint é uma descrição do estilo a ser usado ao desenhar em um Canvas, e Canvas é uma interface para registrar operações gráficas.
Então vamos criar uma classe responsável por isso.
class TouchPoints {
Paint paint;
Offset points;
TouchPoints({this.points, this.paint});
}
Criar campo para capturar o toque
Criar as variáveis para adicionar os pontos.
GlobalKey globalKey = GlobalKey();
List<TouchPoints> points = [];
StrokeCap strokeType = StrokeCap.round;
double strokeWidth = 3.0;
Color selectedColor = Colors.black;
double opacity = 1.0;
Criar campo para capturar evento do toque.
GestureDetector(
onPanUpdate: (details) {
setState(() {
RenderBox renderBox = context.findRenderObject();
points.add(_criarTouchPoints(renderBox, details));
});
},
onPanStart: (details) {
setState(() {
RenderBox renderBox = context.findRenderObject();
points.add(_criarTouchPoints(renderBox, details));
});
},
onPanEnd: (details) {
setState(() {
points.add(null);
});
},
child: RepaintBoundary(
key: globalKey,
child: CustomPaint(
size: Size.infinite,
painter: MyPainter(pointsList: points),
),
),
),
Função responsável por adicionar os pontos.
TouchPoints _criarTouchPoints(renderBox, details) {
return TouchPoints(
points: renderBox.globalToLocal(details.globalPosition),
paint: Paint()
..strokeCap = strokeType
..isAntiAlias = true
..color = selectedColor.withOpacity(opacity)
..strokeWidth = strokeWidth);
}
Adicionar os pontos no Canvas
Classe usada no CustomPainter para desenhar.
@override
void paint(Canvas canvas, Size size) {
for (int i = 0; i < pointsList.length - 1; i++) {
if (pointsList[i] != null && pointsList[i + 1] != null) {
// Desenhar linha quando dois pontos consecutivos estiverem disponíveis
canvas.drawLine(pointsList[i].points, pointsList[i + 1].points, pointsList[i].paint);
} else if (pointsList[i] != null && pointsList[i + 1] == null) {
offsetPoints.clear();
offsetPoints.add(pointsList[i].points);
offsetPoints.add(Offset(pointsList[i].points.dx + 0.1, pointsList[i].points.dy + 0.1));
//Desenhe pontos quando dois pontos não estiverem próximos um do outro
canvas.drawPoints(ui.PointMode.points, offsetPoints, pointsList[i].paint);
}
}
}
Transformar em uma imagem
Precisamos pegar todos os pontos rastreados no nosso Canvas e transformalo em bytes.
RenderRepaintBoundary boundary = globalKey.currentContext.findRenderObject();
ui.Image image = await boundary.toImage();
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
Depois passar esses bytes para este Widget para criar uma imagem.
Image.memory(pngBytes)
Conclusão
Aprender a fundo como as coisas funcionar é muito importante, pode esclarecer vários pontos que passa despercebido.
Espero ter ajudado, valeu!
Referências:
Plugin Signature
Flutter Paint Class
Flutter Canvas Class
Flutter Offset Class
Video do canal Flutter sobre CustomPaint
Top comments (0)