In mobile app development, displaying PDF files is a common requirement. Whether you’re building a document reader, an e-book application, or an app that needs to show reports, being able to render PDF files is essential. In Flutter, this can be achieved using the flutter_pdfview
package. This article guides you on how to use flutter_pdfview
to display PDF files in your Flutter application effectively.
Why Display PDF Files in Flutter?
- Document Display: Render various types of documents like user manuals, reports, and invoices directly within the app.
- E-Book Integration: Develop e-book readers capable of displaying PDF format e-books.
- Offline Accessibility: Allow users to access critical documents even without an internet connection by storing the PDF files locally.
Prerequisites
Before diving in, ensure you have:
- Flutter SDK installed on your machine.
- An IDE such as VS Code or Android Studio.
- Basic knowledge of Flutter development.
Step-by-Step Guide to Using flutter_pdfview
Step 1: Add flutter_pdfview
Dependency
Add the flutter_pdfview
package to your pubspec.yaml
file:
dependencies:
flutter:
sdk: flutter
flutter_pdfview: ^3.2.0 # Use the latest version
Then, run flutter pub get
to install the package.
Step 2: Import the Package
In your Dart file, import the flutter_pdfview
package:
import 'package:flutter_pdfview/flutter_pdfview.dart';
Step 3: Basic PDF Display
To display a PDF file, you need to create a PDFView
widget. Here’s a basic example to load a PDF file from an asset:
import 'package:flutter/material.dart';
import 'package:flutter_pdfview/flutter_pdfview.dart';
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
class PDFScreen extends StatefulWidget {
@override
_PDFScreenState createState() => _PDFScreenState();
}
class _PDFScreenState extends State {
String assetPath = '';
@override
void initState() {
super.initState();
loadAsset();
}
Future loadAsset() async {
// Load PDF file from assets
final assetData = await rootBundle.load('assets/sample.pdf');
final bytes = assetData.buffer.asUint8List();
// Get the application documents directory
final appDir = await getApplicationDocumentsDirectory();
final file = File('${appDir.path}/sample.pdf');
// Write the PDF data to the file
await file.writeAsBytes(bytes, flush: true);
setState(() {
assetPath = file.path;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("PDF Viewer"),
),
body: assetPath.isEmpty
? Center(child: CircularProgressIndicator())
: PDFView(
filePath: assetPath,
),
);
}
}
Ensure that the PDF file sample.pdf
is in your assets
directory, and that the assets
directory is properly declared in your pubspec.yaml
file:
flutter:
assets:
- assets/sample.pdf
Explanation:
- The code loads a PDF from the assets folder using
rootBundle.load
. - It then writes the data to a temporary file in the app’s documents directory using
path_provider
. - The
PDFView
widget is then used to display the PDF file from the local path.
Step 4: Load PDF from Network
To load a PDF from a URL, use the PDFView
widget with the fromUrl
method. Here’s how:
import 'package:flutter/material.dart';
import 'package:flutter_pdfview/flutter_pdfview.dart';
class PDFScreen extends StatelessWidget {
final String remotePDFpath = "https://www.africau.edu/images/default/sample.pdf"; // Replace with a valid PDF URL
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("PDF from URL"),
),
body: PDFView(
filePath: remotePDFpath,
enableSwipe: true,
swipeHorizontal: true,
autoSpacing: false,
pageFling: false,
),
);
}
}
Step 5: Handle PDF Loading States and Errors
Use PDFViewController
to manage the PDF view, load pages, and handle errors:
import 'package:flutter/material.dart';
import 'package:flutter_pdfview/flutter_pdfview.dart';
class PDFScreen extends StatefulWidget {
final String assetPath;
PDFScreen({required this.assetPath});
@override
_PDFScreenState createState() => _PDFScreenState();
}
class _PDFScreenState extends State {
bool _isLoading = true;
PDFViewController? _pdfViewController;
int _totalPages = 0;
int _currentPage = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('PDF Viewer'),
actions: [
if (_totalPages > 0)
Center(child: Text('$_currentPage/$_totalPages', style: TextStyle(fontSize: 18))),
SizedBox(width: 16)
],
),
body: Stack(
children: [
PDFView(
filePath: widget.assetPath,
enableSwipe: true,
swipeHorizontal: false,
autoSpacing: false,
pageFling: true,
onRender: (_pages) {
setState(() {
_totalPages = _pages!;
_isLoading = false;
});
},
onViewCreated: (PDFViewController vc) {
_pdfViewController = vc;
},
onPageChanged: (int? page, int? total) {
setState(() {
_currentPage = page!;
});
},
),
_isLoading ? Center(child: CircularProgressIndicator()) : Container(),
],
),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
child: Icon(Icons.chevron_left, size: 30,),
onPressed: () {
if (_currentPage > 0) {
_pdfViewController?.setPage(_currentPage - 1);
}
},
),
SizedBox(width: 10),
FloatingActionButton(
child: Icon(Icons.chevron_right, size: 30,),
onPressed: () {
if (_currentPage < _totalPages) {
_pdfViewController?.setPage(_currentPage + 1);
}
},
),
],
),
);
}
}
Key functionalities and explanations:
- Loading State Management: Displays a
CircularProgressIndicator
while the PDF is loading using the_isLoading
flag. - PDFViewController: Manages the PDF viewer, allowing programmatic control such as changing pages.
- Total Pages and Current Page: Tracks and displays the current page number and total page count.
- Page Navigation: Floating action buttons for navigating between pages.
- Callbacks:
onRender
: Called when the PDF is rendered, updating the total number of pages and setting the loading state to false.onViewCreated
: Called when the PDFView is created, providing the PDFViewController instance.onPageChanged
: Called when the page changes, updating the current page number.
Handling Errors
Add error handling to gracefully manage issues such as PDF loading failures:
PDFView(
filePath: path,
onError: (error) {
print('PDF load error: $error');
// Handle error appropriately
},
onPageError: (page, error) {
print('Error on page $page: $error');
// Handle error for a specific page
}
)
Conclusion
Displaying PDF files in Flutter using the flutter_pdfview
package is straightforward. Whether loading from assets or a remote URL, this guide provides the essential steps to get you started. By utilizing the PDFView widget along with handling states and errors, you can create a robust and user-friendly PDF viewing experience in your Flutter applications.