Blog post

Flutter PDF viewer: How to build and integrate a PDF viewer in Flutter

Jonathan D. Rhyne Jonathan D. Rhyne

Integrating a Flutter PDF viewer into your mobile application is essential for displaying documents like user manuals, reports, eBooks, and more. Whether you’re building an educational app, a business tool, or an e-reader, a PDF viewer enhances user experience by allowing seamless document interaction. Flutter, with its rich ecosystem of packages, makes it easy to implement a PDF viewer with features like zooming, scrolling, and text search.

Illustration: Flutter PDF viewer: How to build and integrate a PDF viewer in Flutter

This post will walk you through the process of setting up a basic PDF viewer in Flutter to handle single-page documents.

Flutter is an open source framework developed by Google that allows for creating natively compiled applications for mobile, web, and desktop from a single codebase in Dart.

The post will start by exploring how to choose the right package for PDF viewing from a range of open source options. Then, you’ll proceed to integrate the selected package into a Flutter project, resulting in a functional PDF viewer app.

Choosing the right PDF package for Flutter

When selecting a PDF library for Flutter, it’s essential to evaluate your requirements and consider factors like package quality and functionality. For simple use cases, exploring open source libraries is a great starting point. For more advanced needs, Nutrient offers a robust Flutter PDF SDK with comprehensive features.

To find suitable packages, searching for pdf on pub.dev reveals a plethora of options. Key factors to consider include:

  • Pub points — Reflects the quality of the package based on static analysis, including support for null safety and adherence to Dart conventions.

  • Popularity — Indicates the number of developers using the package.

  • Update frequency — A recent update date often signifies an actively maintained project.

  • Verified publisher — Some packages come from verified publishers, adding an extra layer of trust.

Among the search results, the following packages are noteworthy:

  • flutter_pdfview — A Flutter plugin that provides a PDFView widget on Android and iOS.

  • native_pdf_view — A Flutter plugin for rendering PDF files on web, macOS, Windows, Android, and iOS.

  • advance_pdf_viewer — A Flutter plugin for handling PDF files.

After a quick assessment of the three packages, flutter_pdfview proved to be the most suitable for the goal of the experiment of implementing a simple PDF viewer. It has an example included in the GitHub repository, the configuration steps are easy to follow, and under its hood, it’s based on a Google library called PDFium — and here at Nutrient, we love PDFium! ❤️

Building a PDF viewer with flutter_pdfview

flutter_pdfview is a Flutter package that allows you to render PDFs on both Android and iOS platforms. It provides a seamless way to display PDF files within your Flutter app, offering features such as page navigation, zooming, and more. It exposes some configuration options to provide a customized experience, and there’s an example app included in the GitHub repository.

To keep the use case simple, this post will use flutter_pdfview to show a single-page PDF document on an Android device with API 30.

The main layout of the app will be a widget showing the rendered PDF document, and it’ll allow simple gestures like pinch-to-zoom and dragging the zoomed page.

Getting started

To get started, ensure you have Flutter installed and set up on your development machine. You can check this by running the following command:

flutter doctor

This command will verify if you have everything in place to start developing with Flutter.

Step 1 — Creating a new Flutter project

Begin by creating a new Flutter project. Open your terminal and run:

flutter create pdf_viewer_app

Navigate to your project directory:

cd pdf_viewer_app

Step 2 — Adding the flutter_pdfview dependency

Next, add the flutter_pdfview package to your pubspec.yaml file under dependencies:

...
dependencies:
  flutter:
    sdk: flutter
+ flutter_pdfview: ^1.2.7
...

Be careful with the above, as spaces matter in YAML files.

Run flutter pub get to install the package.

Step 3 — Updating the Android and iOS configurations

For Android, ensure your minSdkVersion is at least 21 in android/app/build.gradle:

defaultConfig {
    ...
    minSdkVersion 21
    ...
}

For iOS, enable Swift support by adding the following to your ios/Podfile:

platform :ios, '11.0'

Then, install the dependencies:

cd ios
pod install
cd ..

Step 4 — Creating the PDF viewer widget

Now you’ll create the PDF viewer widget. Open lib/main.dart and replace its content with the following code:

import 'package:flutter/material.dart';
import 'package:flutter_pdfview/flutter_pdfview.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
import 'dart:async';
import 'package:flutter/services.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: PDFScreen(),
    );
  }
}

class PDFScreen extends StatefulWidget {
  @override
  _PDFScreenState createState() => _PDFScreenState();
}

class _PDFScreenState extends State<PDFScreen> {
  String? _localPath;
  int? _totalPages = 0;
  int? _currentPage = 0;
  bool pdfReady = false;
  late PDFViewController _pdfViewController;

  @override
  void initState() {
    super.initState();
    fromAsset('assets/sample.pdf', 'sample.pdf').then((file) {
      setState(() {
        _localPath = file.path;
        pdfReady = true;
      });
    });
  }

  Future<File> fromAsset(String asset, String fileName) async {
    final byteData = await rootBundle.load(asset);
    final file = File('${(await getTemporaryDirectory()).path}/$fileName');
    await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
    return file;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('PDF Viewer'),
        actions: _totalPages != null
            ? <Widget>[
                Center(child: Text('${_currentPage! + 1} / $_totalPages')),
                IconButton(
                  icon: Icon(Icons.chevron_left),
                  onPressed: () {
                    setState(() {
                      _currentPage = (_currentPage! - 1).clamp(0, _totalPages! - 1);
                    });
                    _pdfViewController.setPage(_currentPage!);
                  },
                ),
                IconButton(
                  icon: Icon(Icons.chevron_right),
                  onPressed: () {
                    setState(() {
                      _currentPage = (_currentPage! + 1).clamp(0, _totalPages! - 1);
                    });
                    _pdfViewController.setPage(_currentPage!);
                  },
                ),
              ]
            : null,
      ),
      body: pdfReady
          ? PDFView(
              filePath: _localPath,
              enableSwipe: true,
              swipeHorizontal: true,
              autoSpacing: false,
              pageFling: false,
              onRender: (_pages) {
                setState(() {
                  _totalPages = _pages;
                });
              },
              onViewCreated: (PDFViewController vc) {
                _pdfViewController = vc;
              },
              onPageChanged: (page, total) {
                setState(() {
                  _currentPage = page;
                });
              },
              onError: (error) {
                print(error.toString());
              },
              onPageError: (page, error) {
                print('$page: ${error.toString()}');
              },
            )
          : Center(child: CircularProgressIndicator()),
    );
  }
}

Step 5 — Adding a sample PDF

Add a sample PDF document named sample.pdf to your assets folder. If the folder doesn’t exist, create it in the root directory of your project. Then, update your pubspec.yaml file to include the assets:

flutter:
+  assets:
+    - assets/sample.pdf

Step 6 — Running the app

To run the PDF viewer, make sure to connect a physical Android device or open an emulator from the Android Virtual Device Manager. Then from the command line, type:

flutter run

After a short building process, the PDF viewer app will be ready to use on the Android device. 🎉

Troubleshooting and error handling

The following sections outline errors you may encounter and how to deal with them.

flutter_pdfview is not displaying the PDF

  • Ensure the flutter_pdfview dependency is installed by running:

flutter pub get
  • Confirm the PDF file is correctly located in the assets folder and properly referenced in pubspec.yaml.

  • For Android, check that minSdkVersion is set to 21 or higher.

iOS: Podfile issues

  • Run pod install inside the ios directory if you’re encountering issues with missing dependencies.

  • Ensure platform :ios, '11.0' is set in ios/Podfile.

App crashes when loading PDF

  • Confirm you have granted necessary storage permissions on Android.

  • Use try-catch blocks around file loading logic to handle potential errors.

Cons of flutter_pdfview for advanced features

While flutter_pdfview is a solid package for rendering PDFs in Flutter, it does have certain limitations when it comes to advanced features.

  1. Lack of pinch-to-zoom

flutter_pdfview doesn’t support pinch-to-zoom out of the box. While you can enable basic zooming and scrolling through swipe gestures, more advanced zooming behavior — like pinch-to-zoom — will require custom gesture handling or integration with other packages, such as pdf_flutter.

  1. Limited page navigation

While basic page navigation (like swiping between pages) is supported, there’s no built-in support for more advanced navigation controls like a page slider, page jump, or navigation bar. You need to implement custom controls for these features manually.

  1. No native support for annotations or form filling

flutter_pdfview doesn’t have built-in support for adding annotations or filling out forms within the PDF. You can use additional packages such as pdf_render or pdf_text to manipulate the content, but combining them with flutter_pdfview to render the updated content requires additional development work.

  1. No text selection or search functionality

Text selection and search aren’t natively supported in flutter_pdfview. To enable text search and selection, you’ll need to extract the text using packages like pdf_text and build a custom search and selection system. This adds complexity to the implementation.

These limitations mean that flutter_pdfview might not be the best fit if you require these advanced features for your Flutter PDF viewer. You may need to consider other solutions or integrate additional libraries for a full-featured experience.

Conclusion

This post covered some factors to look at when selecting a PDF package from a set of open source packages, and it showed how to build a PDF viewer using the open source Flutter PDF library, flutter_pdfview, which is good for solving simple use cases without too much hassle. However, AndroidPdfViewer — the library flutter_pdfview is based on — hasn’t received an update in a few years, and it’s still published to JCenter, an artifact repository that’s now read-only.

For more complex customizations, Nutrient offers its own Flutter PDF library with a detailed getting started guide. Nutrient ships with many features out of the box, including:

  • A customizable UI that’s simple and easy to use.

  • Embeddable prebuilt tools to easily add functionality like annotating documents, adding digital signatures to a PDF form, and much more.

  • Multiple file type support — from image files (JPG, PNG, TIFF) to PDF documents.

It also features active development cycles with constant improvements and bug fixes. To get started with Nutrient Flutter SDK, check out our free trial. If you have any questions about our Flutter PDF library, please don’t hesitate to reach out to us. We’re happy to help!

FAQ

How do I choose the right PDF package for Flutter? When selecting a PDF package, consider factors like pub points, popularity, update frequency, and whether the package supports your required features. Popular packages for Flutter include flutter_pdfview, native_pdf_view, and advance_pdf_viewer.
How do I integrate flutter_pdfview into my Flutter project? To integrate flutter_pdfview, add it to your pubspec.yaml dependencies, include path_provider for file management, and ensure you have the jcenter() repository in your Android build script. Follow the setup instructions and add your PDF document to the project’s assets.
What are the main features of flutter_pdfview? flutter_pdfview provides a widget for rendering PDFs in Flutter applications. It supports basic functionalities like viewing PDF documents with pinch-to-zoom and page navigation. It uses the AndroidPdfViewer library under the hood for rendering.
Can I customize the PDF viewer with flutter_pdfview? flutter_pdfview offers some configuration options to customize the viewing experience, such as setting up page zoom and scrolling. For more extensive customization, consider using more advanced libraries or integrating with tools like Nutrient.
What should I do if I encounter issues with flutter_pdfview? If you face issues with flutter_pdfview, check the GitHub repository for troubleshooting tips and open issues. For more complex needs, consider alternative solutions like Nutrient Flutter SDK, which offers additional support and features.
Author
Jonathan D. Rhyne
Jonathan D. Rhyne Co-Founder and CEO

Jonathan joined Nutrient in 2014. As CEO, Jonathan defines the company’s vision and strategic goals, bolsters the team culture, and steers product direction. When he’s not working, he enjoys being a dad, photography, and soccer.

Explore related topics

Free trial Ready to get started?
Free trial