Roland Iordache
Roland Iordache

Reputation: 415

Is there any way to create a PDF from a widget using Flutter?

I did some research and find out that you can create PDF with images or texts or by exporting the screenshot, but I want to create much more like in the image below: enter image description here

So what I want to achieve is to have a good resolution for PDF to print the PDF as a book after this. The physical book has a lot of pages and my client wants to create the virtual one.

So, I have the design (as you can see in the image), but I still need to create some text fields, signature and some logic in the widget. How can I export after that to a one page PDF for every widget? Screenshot won't be enough because I think it doesn't have a good quality and ofc the text and everything else won't be suited in the phone screen.

I am thinking to use the basic design and to add manually by code the texts, but I don't know how to export this to a PDF after that.

Upvotes: 3

Views: 10414

Answers (2)

Zia
Zia

Reputation: 683

I had problem in Flutter to generate pdf from a widget

If anyone wants to

generate pdf , image on pdf, custom font, download pdf and display pdf.

I share my work here to help someone.

First install these 3 packages

  pdf: ^3.10.7
  path_provider: ^2.1.2
  open_file: ^3.3.2

You may add some below permissions

ios (info.plist)

<key>LSSupportsOpeningDocumentsInPlace</key>
    <true/>
    <key>UIFileSharingEnabled</key>
    <true/>

android (AndroidManifest.xml)

   <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

You must import below in your Class

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:flutter/services.dart' show rootBundle;

Below is my download function


  void _printScreen(statement) async {
   final Directory? directory;
    final ByteData fontData =
        await rootBundle.load('assets/fonts/Outfit/static/Outfit-Regular.ttf');
    final ttf = pw.Font.ttf(fontData.buffer.asByteData());
    final image = pw.MemoryImage(
      (await rootBundle.load('assets/images/logo_text.png'))
          .buffer
          .asUint8List(),
    );
    try {
      final doc = pw.Document();
      doc.addPage(pw.Page(
          pageFormat: PdfPageFormat.a4,
          build: (pw.Context context) {
            return pw.ListView(
              children: [
                pw.Container(
                  padding: pw.EdgeInsets.fromLTRB(10, 0, 10, 0),
                  child: pw.Column(
                    mainAxisAlignment: pw.MainAxisAlignment.start,
                    crossAxisAlignment: pw.CrossAxisAlignment.start,
                    children: [
                      pw.Image(
                        image,
                        width: 120,
                        fit: pw.BoxFit.contain,
                      ),
                      pw.SizedBox(height: 50),
                      pw.Text(
                        "${widget.statement.name}",
                        style: pw.TextStyle(font: ttf),
                      ),
                      pw.Text(
                        "${widget.statement.phone}",
                        style: pw.TextStyle(font: ttf),
                      ),
                      pw.Text(
                        "${widget.statement.email}",
                        style: pw.TextStyle(font: ttf),
                      ),
                      pw.SizedBox(height: 50),
                      pw.Row(
                        children: [
                          pw.Text(
                            "${widget.statement.month}",
                            style: pw.TextStyle(
                                fontWeight: pw.FontWeight.bold,
                                font: ttf,
                                fontSize: 20),
                          ),
                          pw.SizedBox(width: 10),
                          pw.Text(
                            "${widget.statement.year}",
                            style: pw.TextStyle(
                                fontWeight: pw.FontWeight.bold,
                                font: ttf,
                                fontSize: 20),
                          ),
                        ],
                      ),
                      pw.Text(
                        "Monthly statement",
                        style: pw.TextStyle(
                          font: ttf,
                          color: PdfColor.fromInt(Colors.grey.value),
                        ),
                      ),
                      pw.SizedBox(height: 30),
                      pw.Row(
                        mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
                        children: [
                          pw.Text(
                            "TOTAL EARNINGS",
                            style: pw.TextStyle(
                                font: ttf,
                                color: PdfColor.fromInt(Colors.grey.value),
                                fontSize: 30,
                                fontWeight: pw.FontWeight.bold),
                          ),
                          pw.Text(
                            "\$${widget.statement.totalEarning}",
                            style: pw.TextStyle(
                                font: ttf,
                                fontSize: 30,
                                fontWeight: pw.FontWeight.bold),
                          ),
                        ],
                      ),
                      pw.SizedBox(height: 50),
                      pw.Text(
                        "Earnings breakdown",
                        style: pw.TextStyle(
                          font: ttf,
                          fontSize: 22,
                          fontWeight: pw.FontWeight.bold,
                          decoration: pw.TextDecoration.underline,
                        ),
                      ),
                      pw.SizedBox(height: 30),
                      pw.Row(
                        children: [
                          pw.SizedBox(
                              width: 120,
                              child: pw.Text(
                                "Moving cost",
                                style: pw.TextStyle(font: ttf),
                              )),
                          pw.Text("\$${widget.statement.movingCost}"),
                        ],
                      ),
                      pw.Row(
                        children: [
                          pw.SizedBox(
                              width: 120,
                              child: pw.Text(
                                "Travel cost",
                                style: pw.TextStyle(font: ttf),
                              )),
                          pw.Text("\$${widget.statement.travelCost}"),
                        ],
                      ),
                      pw.Row(
                        children: [
                          pw.SizedBox(
                              width: 120,
                              child: pw.Text(
                                "Service fee",
                                style: pw.TextStyle(font: ttf),
                              )),
                          pw.Text("\$${widget.statement.serviceFee}"),
                        ],
                      ),
                      pw.Row(
                        children: [
                          pw.SizedBox(
                              width: 120,
                              child: pw.Text(
                                "GST",
                                style: pw.TextStyle(font: ttf),
                              )),
                          pw.Text("\$${widget.statement.gst}"),
                        ],
                      ),
                      pw.Row(
                        children: [
                          pw.SizedBox(
                              width: 120,
                              child: pw.Text(
                                "Tips",
                                style: pw.TextStyle(font: ttf),
                              )),
                          pw.Text("\$${widget.statement.tips}"),
                        ],
                      ),
                      pw.Row(
                        children: [
                          pw.SizedBox(
                              width: 120,
                              child: pw.Text(
                                "Refunds",
                                style: pw.TextStyle(font: ttf),
                              )),
                          pw.Text("\$${widget.statement.refund}"),
                        ],
                      ),
                      pw.SizedBox(height: 50),
                      pw.Text(
                        "Total number of jobs completed for the month ${widget.statement.numberOfJobs}",
                        style: pw.TextStyle(font: ttf),
                      ),
                      pw.SizedBox(height: 80),
                      pw.Text(
                        "THIS IS NOT AN OFFICIAL INVOICE OR TAX DOCUMENT",
                        style: pw.TextStyle(
                          font: ttf,
                          fontSize: 20,
                          color: PdfColor.fromInt(Colors.grey.value),
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            );
          }));

if (Platform.isIOS) {
        directory = await getApplicationDocumentsDirectory();
      } else {
        directory = await getDownloadsDirectory();
      }

      if (directory == null) {
        CustomSnackbar.showBottom(context, "Document directory not available");
        return;
      }
      String path = directory.path;
      String myFile =
          '${path}/Tingsapp-statement-${statement.month}-${statement.year}.pdf';
      final file = File(myFile);
      await file.writeAsBytes(await doc.save());
      OpenFile.open(myFile);
    } catch (e) {
      debugPrint("$e");
      CustomSnackbar.showBottom(context, "$e");
    }
  }

I hope this help someone.

Upvotes: 1

jbryanh
jbryanh

Reputation: 2013

Of Course! The pdf package is a great start.

Upvotes: 3

Related Questions