7

i want to create a signature area like Here with dart in a mobile app!

I tried to use the CustomPaint class ... But it doesn't work.

Can anyone help me?

Shady Aziza
  • 50,824
  • 20
  • 115
  • 113
Jona
  • 273
  • 1
  • 2
  • 5
  • 7
    We discourage posts that simply state a problem out of context, and expect the community to solve it. Assuming you tried to solve it yourself and got stuck, it may be helpful if you wrote your thoughts and what you could not figure out. Add an [mcve] of your code, and describe what problems you're having. _"But it doesn't work"_ isn't very helpful. – Cerbrus Oct 11 '17 at 08:28
  • 1
    Your program [doesn't work](http://importblogkit.com/2015/07/does-not-work/)? – Robert Columbia Oct 11 '17 at 12:03
  • Can the delete voter explain their vote? The answer posted here seems rather helpful.... – user000001 Oct 11 '17 at 19:35
  • 3
    [The Meta effect](https://meta.stackoverflow.com/questions/357689/is-this-a-right-question-for-an-audit), @user000001. I agree that deletion is completely unwarranted, given the high quality answer. If it gets deleted anyway, please flag it. – Cody Gray - on strike Oct 12 '17 at 09:20

1 Answers1

60

You can create a signature area using GestureDetector to record touches and CustomPaint to draw on the screen. Here are a few tips:

video

import 'package:flutter/material.dart';

class SignaturePainter extends CustomPainter {
  SignaturePainter(this.points);

  final List<Offset> points;

  void paint(Canvas canvas, Size size) {
    Paint paint = new Paint()
      ..color = Colors.black
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 5.0;
    for (int i = 0; i < points.length - 1; i++) {
      if (points[i] != null && points[i + 1] != null)
        canvas.drawLine(points[i], points[i + 1], paint);
    }
  }

  bool shouldRepaint(SignaturePainter other) => other.points != points;
}

class Signature extends StatefulWidget {
  SignatureState createState() => new SignatureState();
}

class SignatureState extends State<Signature> {
  List<Offset> _points = <Offset>[];

  Widget build(BuildContext context) {
    return new Stack(
      children: [
        GestureDetector(
          onPanUpdate: (DragUpdateDetails details) {
            RenderBox referenceBox = context.findRenderObject();
            Offset localPosition =
                referenceBox.globalToLocal(details.globalPosition);

            setState(() {
              _points = new List.from(_points)..add(localPosition);
            });
          },
          onPanEnd: (DragEndDetails details) => _points.add(null),
        ),
        CustomPaint(painter: SignaturePainter(_points), size: Size.infinite),
      ],
    );
  }
}

class DemoApp extends StatelessWidget {
  Widget build(BuildContext context) => new Scaffold(body: new Signature());
}

void main() => runApp(new MaterialApp(home: new DemoApp()));
Collin Jackson
  • 110,240
  • 31
  • 221
  • 152
  • This code does not seem to work anymore with the beta channel of flutter. I tried on emulator and on a real device (Pixel 2) but nothing draws on the screen. – xrd Mar 10 '18 at 06:58
  • 3
    @xrd i changed structure a bit, please check the gist here: https://gist.github.com/kitttn/408aa1264b82ae8ce1c0098a270e4f52 – Nikita Kraev Mar 14 '18 at 18:26
  • @xrd please note you should enable Dart 2 support in your IDE / analyzer. Or just manually add `new` in children constructor invocations. – Nikita Kraev Mar 14 '18 at 18:27
  • @NikitaKraev thank you. How can I make it more performant? If I keep drawing I loose the 60 fps and gets into like 5 fps and becomes very slow. Is there a way to make it more performant. Im creating more like a drawing app. Thank you. – user983327 Apr 15 '18 at 19:05
  • Refer to @Nikita Kraev `s link. It works with dart at 2018.5.2, while Collin Jackson answer not. – xingjiu May 02 '18 at 02:21
  • I couldn't get this code to run until I modified: `child: new CustomPaint(painter: new SignaturePainter(_points)),` with the replacement `child: CustomPaint(painter: SignaturePainter(_points), size: Size.infinite),` – zipzit Jul 28 '18 at 20:32
  • I've updated the code with the suggestions in the comments – Collin Jackson Dec 11 '18 at 19:42
  • @CollinJackson how can I delete the last line? removeLast() doesn't work as expected. – Sarah Pöhler Jan 31 '19 at 22:39
  • 1
    I had to switch GestureDetector and CustomPaint, otherwiser the onPanUpdate was not triggered – Gpack Aug 20 '19 at 07:06
  • I would clamp localPostion, so that the signing doesn't overflow the signature widget size : localPosition = Offset( localPosition.dx.clamp(0.0, referenceBox.size.width), localPosition.dy.clamp(0.0, referenceBox.size.height), ); – user6097845 Aug 26 '20 at 17:33