How to build a Flutter PDF viewer
This article was first published in March 2022 and was updated in September 2024.
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. This post will walk through the process of setting up a basic PDF viewer in Flutter to handle single-page documents.
It’ll 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 aPDFView
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'
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. 🎉
Conclusion
In this blog post, we covered some factors to look at when selecting a PDF package from a set of open source packages, and we showed you 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
Here are a few frequently asked questions about building a Flutter PDF viewer.
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.