DEV Community

Cover image for Como fazer campo de assinatura ou desenho em Flutter.
Joabe Ramone
Joabe Ramone

Posted on

Como fazer campo de assinatura ou desenho em Flutter.

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,
  );
Enter fullscreen mode Exit fullscreen mode

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,
      )
Enter fullscreen mode Exit fullscreen mode

Depois de assinar você pode pegar os bytes em png do controlador e transformar isso em uma imagem.

Image.memory(_controller.toPngBytes())
Enter fullscreen mode Exit fullscreen mode

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});
}
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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),
          ),
        ),
      ),
Enter fullscreen mode Exit fullscreen mode

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);
  }
Enter fullscreen mode Exit fullscreen mode

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);
      }
    }
  }
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

Depois passar esses bytes para este Widget para criar uma imagem.

Image.memory(pngBytes)
Enter fullscreen mode Exit fullscreen mode

Conclusão

Aprender a fundo como as coisas funcionar é muito importante, pode esclarecer vários pontos que passa despercebido.

Espero ter ajudado, valeu!

GitHub

Referências:
Plugin Signature
Flutter Paint Class
Flutter Canvas Class

Flutter Offset Class
Video do canal Flutter sobre CustomPaint

Top comments (0)