How to capture a whole painting when its scrolled out in flutter custom paint

55 Views Asked by At

This is the code - I implemented a custom paint widget to draw a drawing, but when I scroll the things up or down, the painting which is go outside of the screen is not captured.

I work for this thing from very long time but I am unable to do it by myself.

Image of the drawing app

image of pdf file

Please can someone help me to figure this out?

Future<void> captureAndSaveImage(
    {ui.PictureRecorder? recorder, GlobalKey? repaintKey}) async {
  RenderRepaintBoundary boundary =
      repaintKey!.currentContext!.findRenderObject() as RenderRepaintBoundary;
  ui.Image image = await boundary.toImage(pixelRatio: 10.0);
  ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
  Uint8List uint8List = byteData!.buffer.asUint8List();

  print(byteData);
  final pdf = pdf_widgets.Document();
  //Request permissions if not already granted
  if (!(await Permission.storage.status.isGranted))
    await Permission.storage.request();

  pdf.addPage(
    pdf_widgets.Page(
      // pageFormat: PdfPageFormat.a3,
      build: (pdf_widgets.Context context) {
        return pdf_widgets.Image(
          pdf_widgets.MemoryImage(uint8List),
        );
      },
    ),
  );

  //get the date to set name of the file
  DateTime now = DateTime.now();
  DateTime date =
      DateTime(now.year, now.month, now.day, now.hour, now.minute, now.second);

  final directory = await getDownloadsDirectory();
  final file = File('${directory!.path}/${date.toString()}.pdf');
  await file.writeAsBytes(await pdf.save());

  print('File saved to ${file.path}');
}


enum CanvasState { draw, panUpdate }

class PaintPrescription extends StatefulWidget {
  const PaintPrescription({super.key});
  static String id = 'paintPrescription';

  @override
  State<PaintPrescription> createState() => _PaintPrescriptionState();
}

class _PaintPrescriptionState extends State<PaintPrescription> {
  List<List<Offset>> points = [];
  List<List<Offset>> redoStack = [];
  List<Offset> currentPath = [];
  Offset offset = Offset(0, 0);
  CanvasState canvasState = CanvasState.draw;
  final recorder = ui.PictureRecorder();
  final GlobalKey _repaintKey = GlobalKey();
  late Canvas canvas;

  @override
  void initState() {
    super.initState();
    canvas = Canvas(recorder);
  }

  void _changeMode() {
    setState(() {
      canvasState = (canvasState == CanvasState.draw)
          ? CanvasState.panUpdate
          : CanvasState.draw;
    });
  }

  Widget _appBarButtons(
      {required void onPressed(), required IconData iconData}) {
    return Padding(
      padding: const EdgeInsets.only(top: 15.0),
      child: IconButton(
          onPressed: onPressed,
          icon: Icon(
            iconData,
            size: 27.0,
            color: kAppBlue,
          )),
    );
  }

  @override
  Widget build(BuildContext coheightntext) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        backgroundColor: Colors.white,
        actions: [
          _appBarButtons(onPressed: _undo, iconData: Icons.undo_rounded),
          _appBarButtons(onPressed: _redo, iconData: Icons.redo_rounded),
          _appBarButtons(
              onPressed: _changeMode,
              iconData: canvasState == CanvasState.panUpdate
                  ? Icons.swipe_vertical_rounded
                  : Icons.swipe_vertical_outlined)
        ],
      ),

      //body
      body: GestureDetector(
        onScaleStart: (details) => _startPath(details.localFocalPoint),
        onScaleUpdate: (details) {
          if (canvasState == CanvasState.panUpdate)
            _updatePan(details.focalPointDelta);
          else
            _updatePath(details.localFocalPoint);
        },
        onScaleEnd: (_) => _endPath(),
        child: RepaintBoundary(
          key: _repaintKey,
          child: SizedBox(
            width: MediaQuery.of(context).size.width,
            height: double.infinity,
            child: SingleChildScrollView(
              child: CustomPaint(
                painter: PrescriptionWritter(points, offset),
              ),
            ),
          ),
        ),
      ),

      //send button
      floatingActionButton: FloatingActionButton(
        onPressed: () =>
            captureAndSaveImage(recorder: recorder, repaintKey: _repaintKey),
        backgroundColor: kPrimaryColor,
        child: Icon(Icons.send_rounded),
      ),
    );
  }
}

class PrescriptionWritter extends CustomPainter {
  final List<List<Offset>> points;
  Offset offset;

  PrescriptionWritter(this.points, this.offset);
  var currentPaint = Paint()
    ..color = Colors.black
    ..strokeCap = StrokeCap.round
    ..strokeWidth = 3.0;

  @override
  void paint(canvas, Size size) {
    for (final path in points) {
      for (int i = 0; i < path.length - 1; i++) {
        if (path[i] != Offset(-1, -1) && path[i + 1] != Offset(-1, -1)) {
          canvas.drawLine(
            path[i] + offset,
            path[i + 1] + offset,
            currentPaint,
          );
        } else if (path[i] != Offset(-1, -1) && path[i + 1] == Offset(-1, -1)) {
          canvas.drawPoints(
            ui.PointMode.points,
            [path[i] + offset],
            currentPaint,
          );
        }
      }
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}
0

There are 0 best solutions below