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.
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;
}
}