Search code examples
flutterpdfpdf-generation

Inserting page number on generated PDF file in Flutter


I am creating a PDF file in my Flutter app.

class PdfDiarioApi {

  late Uint8List logobytes;
  late PdfImage _logoImage;
  final List<dynamic> listaRecibida;

  final image = pw.MemoryImage(
    File('imagenes/zf.png').readAsBytesSync(),
  );

  PdfDiarioApi(this.listaRecibida);

  static Future<File> generate(String fecha, String id, List<dynamic> listaDiarioActual, String turno, String patrulla, String vigilante1, String vigilante2, String inicio, String responsable, String firma) async {final pdf = Document();


    DiarioModelo primer = listaDiarioActual[0];

    final firma_resp = await networkImage(Constantes.flutterAPI+"firmas/${firma}");

    final imageByteData = await rootBundle.load('imagenes/zf.png');
    // Convert ByteData to Uint8List
    final imageUint8List = imageByteData.buffer
        .asUint8List(imageByteData.offsetInBytes, imageByteData.lengthInBytes);

    final image = pw.MemoryImage(imageUint8List);
    

    DateTime tempDateI =
    new DateFormat("dd-MM-yyyy HH:mm")
        .parse(inicio);

    String date1 = DateFormat("dd-MM-yyyy HH:mm")
        .format(tempDateI);

    String fecha = DateFormat("dd-MM-yyyy")
        .format(tempDateI);

    String hora = DateFormat("HH:mm")
        .format(tempDateI);



    pdf.addPage(MultiPage(
      maxPages: 20,
      pageFormat: PdfPageFormat.a4,
      build: (context) => [

      pw.SizedBox(height: 25),

      buildTablaDiario(listaDiarioActual),
        
      ],
      header: (context) => buildHeader(image,fecha,patrulla,responsable,vigilante1,vigilante2,turno,hora),
      footer: (context) => buildFooter(firma_resp),
    ));

    return PdfApi.saveDocument(name: 'diario.pdf', pdf: pdf);
  }



  static Widget buildTablaDiario(List<dynamic> listaDiarioActual){



    return ListView.builder(
        itemCount: listaDiarioActual.length,

        itemBuilder: (pw.Context context, index){

          DiarioModelo diario = listaDiarioActual[index];



          DateTime tempDateI =
          new DateFormat("yyyy-MM-dd HH:mm:ss")
              .parse(diario.fecha_diario);

          String date1 = DateFormat("dd-MM-yyyy HH:mm")
              .format(tempDateI);
          String hora = DateFormat("HH:mm")
              .format(tempDateI);
          return pw.Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [

              pw.Row(
                mainAxisAlignment: pw.MainAxisAlignment.start,
                crossAxisAlignment: pw.CrossAxisAlignment.start,
                children: [
                  pw.Text("${hora}",style: pw.TextStyle()),
                  pw.SizedBox(width: 10),
                  pw.Container(
                    width: 320 ,
                    child: pw.Text(diario.descripcion,maxLines: 100),
                  ),


                ]
              ),
              pw.SizedBox(height: 15),

            ]

          );

        }

    );
 }

 static Widget buildHeader(MemoryImage image, String fecha, patrulla,responsable,vigilante1,vigilante2, turno,hora) => Column(
   children: [
     pw.Row(

       mainAxisAlignment: pw.MainAxisAlignment.start,
       children: [
         //Text(customer.name, style: TextStyle(fontWeight: FontWeight.bold)),
         //Text(customer.address),
         pw.Image(image,height: 80,width: 180),
         pw.SizedBox(width: 100),
         pw.Row(
             mainAxisAlignment: pw.MainAxisAlignment.center,
             children: [
               pw.Text("INFORME DIARIO",style: pw.TextStyle(fontSize: 16,decoration: pw.TextDecoration.underline))
             ]
         )

       ],
     ),
     pw.SizedBox(height: 5),
     pw.Row(
       crossAxisAlignment: pw.CrossAxisAlignment.center,
       mainAxisAlignment: pw.MainAxisAlignment.start,
       children: [

         pw.Row(
             mainAxisAlignment: pw.MainAxisAlignment.start,
             children: [
               pw.Text("FECHA: ",style: pw.TextStyle(fontSize: 10,fontWeight: FontWeight.bold)),
               pw.SizedBox(width: 15),
               pw.Text("${fecha}",style: pw.TextStyle(fontSize: 14,))
             ]
         )

       ],
     ),
     pw.Row(
       crossAxisAlignment: pw.CrossAxisAlignment.center,
       mainAxisAlignment: pw.MainAxisAlignment.start,
       children: [

         pw.Row(
             mainAxisAlignment: pw.MainAxisAlignment.start,
             children: [
               pw.Text("PATRULLA: ",style: pw.TextStyle(fontSize: 10,fontWeight: FontWeight.bold)),
               pw.SizedBox(width: 15),
               pw.Text("${patrulla}",style: pw.TextStyle(fontSize: 14))
             ]
         )

       ],
     ),

     pw.Row(
       crossAxisAlignment: pw.CrossAxisAlignment.center,
       mainAxisAlignment: pw.MainAxisAlignment.start,
       children: [

         pw.Row(
             mainAxisAlignment: pw.MainAxisAlignment.start,
             children: [
               pw.Text("RESPONSABLE: ",style: pw.TextStyle(fontSize: 10,fontWeight: FontWeight.bold)),
               pw.SizedBox(width: 15),
               pw.Text("${responsable}",style: pw.TextStyle(fontSize: 14))
             ]
         )

       ],
     ),
     pw.SizedBox(height: 10),
     pw.Row(
       crossAxisAlignment: pw.CrossAxisAlignment.center,
       mainAxisAlignment: pw.MainAxisAlignment.start,
       children: [

         pw.Row(
             mainAxisAlignment: pw.MainAxisAlignment.start,
             children: [
               Container(
                   alignment: Alignment.center,
                   width: 200,
                   height: 20,
                   child: Row(
                       children: [
                         pw.Text("V.S.:",style: pw.TextStyle(fontSize: 10,fontWeight: FontWeight.bold)),
                         pw.SizedBox(width: 10),
                         pw.Text("${vigilante1}",style: pw.TextStyle(fontSize: 14 ,)),

                       ]
                   )
               ),
               pw.SizedBox(width: 45),
               Container(
                   alignment: Alignment.center,
                   width: 200,
                   height: 20,
                   child: Row(
                       children: [
                         pw.Text("TURNO DE:",style: pw.TextStyle(fontSize: 10,fontWeight: FontWeight.bold)),
                         pw.SizedBox(width: 10),
                         pw.Text("${turno}",style: pw.TextStyle(fontSize: 14 ))

                       ]
                   )
               ),




             ]
         )

       ],
     ),
     pw.SizedBox(height: 2),
     pw.Row(
       crossAxisAlignment: pw.CrossAxisAlignment.center,
       mainAxisAlignment: pw.MainAxisAlignment.start,
       children: [

         pw.Row(
             mainAxisAlignment: pw.MainAxisAlignment.start,
             children: [
               Container(
                   alignment: Alignment.center,
                   width: 200,
                   height: 20,
                   child: Row(
                       children: [
                         pw.Text("V.S.:",style: pw.TextStyle(fontSize: 10,fontWeight: FontWeight.bold)),
                         pw.SizedBox(width: 10),
                         pw.Text("${vigilante2}",style: pw.TextStyle(fontSize: 14)),

                       ]
                   )
               ),
               pw.SizedBox(width: 45),
               Container(
                   alignment: Alignment.center,
                   width: 200,
                   height: 20,
                   child: Row(
                       children: [
                         pw.Text("TURNO DE:",style: pw.TextStyle(fontSize: 10,fontWeight: FontWeight.bold)),
                         pw.SizedBox(width: 10),
                         pw.Text("${turno}",style: pw.TextStyle(fontSize: 14 ))

                       ]
                   )
               ),




             ]
         ),



       ],
     ),
     pw.SizedBox(height: 5),
     pw.Row(
         mainAxisAlignment: pw.MainAxisAlignment.start,
         children: [
           pw.Text("HORA DE INICIO: ",style: pw.TextStyle(fontSize: 10,fontWeight: FontWeight.bold)),
           pw.SizedBox(width: 15),
           pw.Text("${hora}",style: pw.TextStyle(fontSize: 14))
         ]
     ),


   ]

  );

  static Widget buildFooter(firmafooter) => Row(
    crossAxisAlignment: CrossAxisAlignment.center,
    children: [

      pw.Column(
          children: [
            pw.Text("FIRMA",
                style:
                pw.TextStyle(fontSize: 11,fontWeight: FontWeight.bold)),
            pw.Container(
                height: 100,
                width: 300,
                decoration: BoxDecoration(
                  border: Border.all(width: 1, color: PdfColors.black),
                ),
                child: pw.Image(firmafooter,height: 95,width: 95,fit: BoxFit.fill)
            )

          ]
      ),
      pw.SizedBox(width: 50),
      pw.Container(
        height: 100,
  child:Text("REVISADO CLIENTE",style: pw.TextStyle(fontSize: 10)))

    ],
  );

  static buildSimpleText({
    required String title,
    required String value,
  }) {
    final style = TextStyle(fontWeight: FontWeight.bold);

    return Row(
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: pw.CrossAxisAlignment.end,
      children: [
        Text(title, style: style),
        SizedBox(width: 2 * PdfPageFormat.mm),
        Text(value),
      ],
    );
  }

  static buildText({
    required String title,
    required String value,
    double width = double.infinity,
    TextStyle? titleStyle,
    bool unite = false,
  }) {
    final style = titleStyle ?? TextStyle(fontWeight: FontWeight.bold);

    return Container(
      width: width,
      child: Row(
        children: [
          Expanded(child: Text(title, style: style)),
          Text(value, style: unite ? style : null),
        ],
      ),
    );
  }
}

There is no issue with the generated PDF file, but I woudl like to insert the page number in the footer part of it.

I have been searching for this option, but not able to find the way to insert the page number on each page.


Solution

  • On your buildFooter, You need to pass the context that is coming from pdf package.

    footer: (context) => buildFooter(context, firma_resp),
    

    Therefore now it will be context.pageNumber

      static Widget buildFooter(context, firmafooter) => Row(...
    
       Text('Page ${context.pageNumber}/${context.pagesCount}'),
    

    If you are having material or other context, you can use prefix from pdf BuildContex.