jv_easy_pdf_viewer 1.3.0
jv_easy_pdf_viewer: ^1.3.0 copied to clipboard
A Flutter plugin that provides a simple and customizable PDF viewer for Android and iOS.
jv_easy_pdf_viewer #
A Flutter plugin for handling PDF files on Android and iOS. PDF pages are
rendered natively (PdfRenderer on Android, CGPDF on iOS) and exposed as
ordinary Flutter widgets - no in-app viewer process, no WebView.
Maintained by @jitendravaishnavs.
Originally forked from pdf_viewer.
Installation #
flutter pub add jv_easy_pdf_viewer
Platform notes #
- Android - no permissions required; previews are written to the app's cache directory.
- iOS - no permissions required; previews are written to the app's Caches directory. Text search is powered by PDFKit (iOS 11+).
Loading a PDF #
PDFDocument is the entry point. Pick whichever loader matches your source:
// From assets
PDFDocument doc = await PDFDocument.fromAsset('assets/test.pdf');
// From a URL (cached on disk automatically)
PDFDocument doc = await PDFDocument.fromURL(
'https://example.com/file.pdf',
headers: {'Authorization': 'Bearer ...'},
);
// From a local file
PDFDocument doc = await PDFDocument.fromFile(File('/path/to/file.pdf'));
// From raw in-memory bytes
PDFDocument doc = await PDFDocument.fromBytes(myUint8List);
For URL loading with a download progress callback, use
PDFDocument.fromURLWithDownloadProgress:
PDFDocument.fromURLWithDownloadProgress(
'https://example.com/file.pdf',
downloadProgress: (progress) {
// progress.progress is a nullable 0.0-1.0 value from flutter_cache_manager.
},
onDownloadComplete: (PDFDocument doc) {
// Use the document once the download finishes.
},
);
By default, each loader clears the rendered page preview cache before opening a
new document. Pass clearPreviewCache: false when you need multiple documents
open at the same time, then call PDFDocument.clearPreviewCache() when you are
done with those previews.
Loading individual pages #
PDFPage page = await doc.get(page: 1);
Or stream every page in order:
await for (final page in doc.getAll()) {
// ...
}
Pre-built viewer #
The PDFViewer widget gives you a complete viewer with a page indicator,
page-picker FAB, 4-button navigation bar, and (on iOS) a text search panel:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('PDF')),
body: _isLoading
? const Center(child: CircularProgressIndicator())
: PDFViewer(document: document),
);
}
Viewer parameters #
| Parameter | Default | Description |
|---|---|---|
document |
required | The PDFDocument to display. |
showIndicator |
true |
Show the "page / total" chip. |
showPicker |
true |
Show the jump-to-page FAB. |
showNavigation |
true |
Show the 4-button bottom bar. |
showSearch |
true |
Show the search icon (opens the search overlay). |
indicatorPosition |
topRight |
Where to place the page indicator chip. |
enableSwipeNavigation |
true |
Allow swiping between pages. |
scrollDirection |
horizontal | Axis.horizontal or Axis.vertical. |
lazyLoad |
true |
Render pages on demand rather than all at once. |
controller |
null | Provide your own PageController. |
navigationBuilder |
null | Replace the default bottom bar with a custom widget. |
indicatorBuilder |
null | Replace the default indicator chip with a custom widget. |
progressIndicator |
null | Custom loading widget shown while a page renders. |
onPageChanged |
null | Called with the 0-indexed page number on every swipe. |
onZoomChanged |
null | Called with the current scale factor on every pinch. |
backgroundColor |
null | Background color behind each page. |
pickerButtonColor / pickerIconColor |
null | Override the jump-to-page FAB colors. |
numberPickerConfirmWidget |
Text('OK') |
Confirm button used in the page picker dialog. |
tooltip |
PDFViewerTooltip() |
Labels for navigation and picker controls. |
resizeToAvoidBottomInset |
true |
Passed to the internal Scaffold. |
zoomSteps / minScale / maxScale / panLimit |
null | Zoom and pan tuning. |
Text search (iOS) #
Tap the search icon (top-left) to open the inline search overlay:
- Debounced auto-search - results appear 400 ms after you stop typing.
Aatoggle - case-sensitive matching.Wtoggle - whole-word matching (uses\bregex boundaries via PDFKit).- Match navigation - previous/next buttons cycle through every match across all pages; the viewer jumps to the page automatically.
- "N of M, X on page" counter - always shows where you are.
- Results list - tap the expand icon to see all matches with a highlighted context snippet; tap any row to jump directly to that page.
- Search history - the last 10 queries are shown when the field is empty and focused.
Android - text search is not yet supported. Calling
search()returnsnull; the viewer shows an informational notice instead of crashing.
Using the API directly #
// Returns null on Android, empty list when nothing found,
// or one PDFSearchResult per match on iOS.
final List<PDFSearchResult>? hits = await doc.search(
'flutter',
caseSensitive: false,
wholeWord: false,
);
if (hits == null) {
// platform does not support text search
} else {
for (final hit in hits) {
print('page ${hit.page}: ${hit.context}');
}
}
Sharing / printing #
PDFDocument.filePath exposes the absolute path of the file that the plugin
is reading from. Pass it to share_plus, printing or any other package:
import 'package:share_plus/share_plus.dart';
await Share.shareXFiles([XFile(doc.filePath!)]);
Dependencies #
| Package | Purpose |
|---|---|
| path_provider | Resolving app-local file system paths. |
| flutter_cache_manager | Caching and re-using PDFs downloaded from a URL. |
| numberpicker | The "jump to page" picker dialog. |
| plugin_platform_interface | Boilerplate for the platform-channel plugin. |