widget_to_pdf_kit 1.0.1 copy "widget_to_pdf_kit: ^1.0.1" to clipboard
widget_to_pdf_kit: ^1.0.1 copied to clipboard

High-performance Flutter widget to PDF generator. Rasterizes onscreen or offscreen widgets into crisp, paginated PDF documents with custom formats and scaling.

example/lib/main.dart

import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:widget_to_pdf_kit/widget_to_pdf_kit.dart';

void main() {
  runApp(const WidgetToPdfExampleApp());
}

class WidgetToPdfExampleApp extends StatelessWidget {
  const WidgetToPdfExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Widget To PDF Kit Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF6366F1),
          brightness: Brightness.light,
        ),
        useMaterial3: true,
      ),
      home: const InvoiceExportScreen(),
    );
  }
}

class InvoiceExportScreen extends StatefulWidget {
  const InvoiceExportScreen({super.key});

  @override
  State<InvoiceExportScreen> createState() => _InvoiceExportScreenState();
}

class _InvoiceExportScreenState extends State<InvoiceExportScreen> {
  final GlobalKey _invoiceKey = GlobalKey();
  bool _isGenerating = false;
  Uint8List? _lastGeneratedPdf;
  String _statusMessage = 'Ready to export PDF';

  Future<void> _exportOnscreenInvoice() async {
    setState(() {
      _isGenerating = true;
      _statusMessage = 'Generating PDF from onscreen invoice...';
    });

    try {
      final stopwatch = Stopwatch()..start();
      final pdfBytes = await WidgetToPdfKit.fromKey(
        _invoiceKey,
        format: PdfPageFormat.a4,
        pixelRatio: 2.5,
      );
      stopwatch.stop();

      setState(() {
        _lastGeneratedPdf = pdfBytes;
        _statusMessage =
            'Success! Generated 1-page PDF (${(pdfBytes.lengthInBytes / 1024).toStringAsFixed(1)} KB) in ${stopwatch.elapsedMilliseconds}ms';
      });
    } catch (e) {
      setState(() {
        _statusMessage = 'Error: $e';
      });
    } finally {
      setState(() {
        _isGenerating = false;
      });
    }
  }

  Future<void> _exportMultiPageOffscreen() async {
    setState(() {
      _isGenerating = true;
      _statusMessage = 'Synthesizing multi-page offscreen report...';
    });

    try {
      final stopwatch = Stopwatch()..start();

      final page1 = _buildOffscreenReportPage(
        pageNumber: 1,
        title: 'Executive Summary & Financial Metrics',
        body: 'Q3 gross transaction volume reached \$4.2M with a 99.98% platform uptime. Operating margin increased by 14.2% quarter-over-quarter.',
      );

      final page2 = _buildOffscreenReportPage(
        pageNumber: 2,
        title: 'User Acquisition & Global Distribution',
        body: 'Active enterprise seats grew from 1,200 to 4,850. International expansion across EMEA contributed 34% of net new ARR.',
      );

      final pdfBytes = await WidgetToPdfKit.fromWidgets(
        context,
        pages: [page1, page2],
        format: PdfPageFormat.a4,
        pixelRatio: 2.0,
      );
      stopwatch.stop();

      setState(() {
        _lastGeneratedPdf = pdfBytes;
        _statusMessage =
            'Success! Generated 2-page PDF (${(pdfBytes.lengthInBytes / 1024).toStringAsFixed(1)} KB) in ${stopwatch.elapsedMilliseconds}ms';
      });
    } catch (e) {
      setState(() {
        _statusMessage = 'Error: $e';
      });
    } finally {
      setState(() {
        _isGenerating = false;
      });
    }
  }

  Widget _buildOffscreenReportPage({
    required int pageNumber,
    required String title,
    required String body,
  }) {
    return Container(
      color: Colors.white,
      padding: const EdgeInsets.all(48),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              const Text(
                'ACME CORP ANNUAL REPORT',
                style: TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.bold,
                  letterSpacing: 1.5,
                  color: Color(0xFF6366F1),
                ),
              ),
              Text(
                'Page $pageNumber of 2',
                style: const TextStyle(color: Colors.grey),
              ),
            ],
          ),
          const Divider(height: 32, thickness: 1),
          const SizedBox(height: 24),
          Text(
            title,
            style: const TextStyle(
              fontSize: 26,
              fontWeight: FontWeight.bold,
              color: Colors.black87,
            ),
          ),
          const SizedBox(height: 16),
          Text(
            body,
            style: const TextStyle(fontSize: 15, height: 1.6, color: Colors.black54),
          ),
          const Spacer(),
          const Text(
            'Confidential - Generated by widget_to_pdf_kit',
            style: TextStyle(fontSize: 11, color: Colors.grey),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFF8FAFC),
      appBar: AppBar(
        title: const Text('Widget To PDF Kit'),
        centerTitle: true,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(20),
        child: Center(
          child: ConstrainedBox(
            constraints: const BoxConstraints(maxWidth: 600),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                // Live Onscreen Invoice Card
                RepaintBoundary(
                  key: _invoiceKey,
                  child: Container(
                    padding: const EdgeInsets.all(24),
                    decoration: BoxDecoration(
                      color: Colors.white,
                      borderRadius: BorderRadius.circular(16),
                      boxShadow: [
                        BoxShadow(
                          color: Colors.black.withValues(alpha: 0.06),
                          blurRadius: 18,
                          offset: const Offset(0, 8),
                        ),
                      ],
                    ),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            Column(
                              crossAxisAlignment: CrossAxisAlignment.start,
                              children: [
                                const Text(
                                  'INVOICE',
                                  style: TextStyle(
                                    fontSize: 22,
                                    fontWeight: FontWeight.bold,
                                    letterSpacing: 1.2,
                                  ),
                                ),
                                Text(
                                  '#INV-2026-089',
                                  style: TextStyle(
                                    color: Colors.grey.shade600,
                                    fontSize: 13,
                                  ),
                                ),
                              ],
                            ),
                            Container(
                              padding: const EdgeInsets.symmetric(
                                horizontal: 12,
                                vertical: 6,
                              ),
                              decoration: BoxDecoration(
                                color: const Color(0xFF10B981).withValues(alpha: 0.15),
                                borderRadius: BorderRadius.circular(8),
                              ),
                              child: const Text(
                                'PAID',
                                style: TextStyle(
                                  color: Color(0xFF10B981),
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                            ),
                          ],
                        ),
                        const Divider(height: 36),
                        _buildLineItem('Cloud Enterprise Subscription', '1x', '\$299.00'),
                        const SizedBox(height: 8),
                        _buildLineItem('Dedicated CDN Bandwidth (10TB)', '1x', '\$150.00'),
                        const SizedBox(height: 8),
                        _buildLineItem('Priority 24/7 SLA Support', '1x', '\$99.00'),
                        const Divider(height: 36),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: const [
                            Text(
                              'Total Amount',
                              style: TextStyle(
                                fontSize: 16,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                            Text(
                              '\$548.00',
                              style: TextStyle(
                                fontSize: 20,
                                fontWeight: FontWeight.bold,
                                color: Color(0xFF6366F1),
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
                const SizedBox(height: 24),

                // Controls
                FilledButton.icon(
                  onPressed: _isGenerating ? null : _exportOnscreenInvoice,
                  icon: const Icon(Icons.picture_as_pdf),
                  label: const Text('Export Onscreen Invoice to PDF'),
                  style: FilledButton.styleFrom(
                    padding: const EdgeInsets.symmetric(vertical: 14),
                  ),
                ),
                const SizedBox(height: 12),
                OutlinedButton.icon(
                  onPressed: _isGenerating ? null : _exportMultiPageOffscreen,
                  icon: const Icon(Icons.layers_outlined),
                  label: const Text('Generate 2-Page Offscreen Report PDF'),
                  style: OutlinedButton.styleFrom(
                    padding: const EdgeInsets.symmetric(vertical: 14),
                  ),
                ),
                const SizedBox(height: 16),

                // Status info
                Container(
                  padding: const EdgeInsets.all(14),
                  decoration: BoxDecoration(
                    color: Colors.grey.shade100,
                    borderRadius: BorderRadius.circular(10),
                    border: Border.all(color: Colors.grey.shade300),
                  ),
                  child: Row(
                    children: [
                      if (_isGenerating)
                        const Padding(
                          padding: EdgeInsets.only(right: 12),
                          child: SizedBox(
                            width: 18,
                            height: 18,
                            child: CircularProgressIndicator(strokeWidth: 2),
                          ),
                        )
                      else
                        Icon(
                          _lastGeneratedPdf != null
                              ? Icons.check_circle
                              : Icons.info_outline,
                          color: _lastGeneratedPdf != null
                              ? Colors.green
                              : Colors.grey,
                          size: 20,
                        ),
                      const SizedBox(width: 8),
                      Expanded(
                        child: Text(
                          _statusMessage,
                          style: const TextStyle(fontSize: 13),
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildLineItem(String item, String qty, String price) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        Expanded(
          child: Text(
            item,
            style: const TextStyle(fontSize: 14, color: Colors.black87),
          ),
        ),
        Text(
          qty,
          style: const TextStyle(fontSize: 14, color: Colors.grey),
        ),
        const SizedBox(width: 24),
        Text(
          price,
          style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
        ),
      ],
    );
  }
}
0
likes
160
points
91
downloads

Documentation

API reference

Publisher

verified publisherbalochcodes.com

Weekly Downloads

High-performance Flutter widget to PDF generator. Rasterizes onscreen or offscreen widgets into crisp, paginated PDF documents with custom formats and scaling.

Repository (GitHub)
View/report issues

Topics

#pdf #printing #export #document #widget

License

MIT (license)

Dependencies

flutter, pdf

More

Packages that depend on widget_to_pdf_kit