A premium, high-performance, native PDF viewer plugin for Flutter. It renders PDFs smoothly via Flutter PlatformViews directly on top of platform-native PDF frameworks:
- Android - PdfRenderer for high-performance page rendering, combined with pdfbox-android for text search and bookmark/outline extraction.
- iOS - PDFKit for full native rendering, text search, and outline support.
The plugin exposes a powerful Dart-side controller and an optional, fully-customizable built-in toolbar for common viewer interactions.
Features
- Open PDFs from assets, network URLs, local file paths, raw bytes (
Uint8List), or base64-encoded strings - Built-in toolbar with page navigation, zoom controls, search, bookmarks, page thumbnails, and a theme toggle - each shown/hidden independently
- Programmatic control via
FlutterPdfToolkitController: jump to page, next / previous page, zoom in / out / reset, search, bookmarks, dark mode, page thumbnails - Horizontal or vertical scrolling, single-page or continuous page modes
- Pinch-to-zoom and double-tap-to-zoom on both Android and iOS
- Initial page and initial zoom level configuration
- Password-protected PDF support, with an automatic unlock dialog
- Dark mode toggle at the Flutter UI level
- Text search with result highlighting and bookmark/outline support on both Android and iOS
- Page thumbnails rendered natively from the PDF and shown in a grid for quick navigation
- Built-in "Sign document" toolbar action: draw a signature, position and resize it on the current page, and stamp it onto the PDF natively via
FlutterPdfToolkit.signPdf() - Built-in "Reorder pages" toolbar action: drag page thumbnails into a new order and save the rearranged PDF natively via
FlutterPdfToolkit.reorderPages() - Built-in "Delete pages" toolbar action: tap page thumbnails to mark them for removal and save the trimmed PDF natively via
FlutterPdfToolkit.removePages() - Built-in "Add pages" toolbar action: pick where to insert new pages from a page-thumbnail grid, then insert PDF and/or image files supplied by the host app natively via
FlutterPdfToolkit.insertPages()andFlutterPdfToolkit.imagesToPdf() - Built-in "Add image" toolbar action: pick an image supplied by the host app, position and resize it on the current page, and stamp it onto the PDF natively via
FlutterPdfToolkit.addImageToPdf() - Merge multiple PDF files into a single document natively via
FlutterPdfToolkit.mergePdfs() - Split a PDF into multiple documents by page range natively via
FlutterPdfToolkit.splitPdf(), withFlutterPdfToolkit.getPdfPageCount()to read a PDF's page count - Save or share a PDF file via
FlutterPdfToolkit.downloadPdf()- saves to the Downloads folder on Android, or opens the share sheet on iOS
Platform Support
Android (API 21 / Android 5.0)
Rendering: PdfRenderer + pdfbox-android
Features: Search and bookmarks via pdfbox-android
iOS (iOS 13.0)
Rendering: PDFKit
Features: Full search and bookmark/outline support
⚠️ Unsupported Platforms
Web, desktop, and macOS are not implemented. FlutterPdfToolkit renders via AndroidView/UiKitView, so usage outside Android/iOS will fail at runtime.
Requirements
- Flutter
>=1.17.0and Dart SDK^3.11.5(as declared inpubspec.yaml). - Android:
minSdkVersion 21or higher (raise it inandroid/app/build.gradleif your app currently targets lower). - iOS: deployment target
13.0or higher (setplatform :ios, '13.0'in yourios/Podfile).
Installation
Add the dependency to your pubspec.yaml:
dependencies:
flutter_pdf_toolkit: ^0.0.1
Then run:
flutter pub get
No additional native setup is required - the plugin registers its platform views automatically on Android and iOS.
If you load PDFs from the network, make sure your app has internet access permission (already enabled by default for Android, and allowed by default on iOS unless you've restricted App Transport Security).
Quick Start
import 'package:flutter/material.dart';
import 'package:flutter_pdf_toolkit/flutter_pdf_toolkit.dart';
class PdfScreen extends StatelessWidget {
const PdfScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('PDF Viewer')),
body: const FlutterPdfToolkit(
source: PdfSource.network(
'https://cdn.syncfusion.com/content/PDFViewer/flutter-succinctly.pdf',
),
),
);
}
}
With a Controller
A FlutterPdfToolkitController lets you drive the viewer programmatically and read its current state (page number, zoom level, bookmarks, search results, etc.).
class PdfScreen extends StatefulWidget {
const PdfScreen({super.key});
@override
State<PdfScreen> createState() => _PdfScreenState();
}
class _PdfScreenState extends State<PdfScreen> {
final FlutterPdfToolkitController _controller = FlutterPdfToolkitController();
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('PDF Viewer'),
actions: [
IconButton(
icon: const Icon(Icons.skip_next),
onPressed: _controller.nextPage,
),
],
),
body: FlutterPdfToolkit(
source: const PdfSource.asset('assets/sample.pdf'),
controller: _controller,
),
);
}
}
PDF Sources
PdfSource is a sealed class with a factory constructor for each supported input type:
// From an asset bundled with your app
const PdfSource.asset('assets/sample.pdf');
const PdfSource.asset('assets/sample.pdf', bundle: myAssetBundle);
// From a network URL, optionally with custom headers (e.g. auth tokens)
const PdfSource.network('https://example.com/sample.pdf');
const PdfSource.network(
'https://example.com/sample.pdf',
headers: {'Authorization': 'Bearer <token>'},
);
// From an absolute local file path
const PdfSource.filePath('/storage/emulated/0/Download/sample.pdf');
// From raw bytes (e.g. downloaded or generated in-memory)
PdfSource.bytes(bytes); // Uint8List
// From a base64-encoded string (data URLs such as "data:application/pdf;base64,..." are also accepted)
PdfSource.base64(base64PdfString);
PdfSource.base64(base64PdfString, password: 'secret');
Internally, asset, network, bytes, and base64 sources are written to a temporary file before being handed to the native viewer; file path sources are passed through as-is.
FlutterPdfToolkit widget reference
Core properties
-
source(PdfSource) - Required. The PDF to display. -
controller(FlutterPdfToolkitController?) - Controller to drive the viewer. If omitted, internal controller is created.
Toolbar controls
-
showToolbar(bool) =true- Show/hide the built-in toolbar. -
showSearch(bool) =true- Show search icon. -
showBookmarks(bool) =true- Show bookmarks icon. -
showThumbnails(bool) =true- Show page thumbnails. -
showZoomControls(bool) =true- Show zoom controls. -
showPageControls(bool) =true- Show prev/next buttons. -
showThemeToggle(bool) =true- Show light/dark toggle.
Document editing
-
showSignature(bool) =true- Show "Sign document" icon. -
onSigned(void Function(String)?) - Called with signed file path. -
showReorder(bool) =true- Show "Reorder pages" icon. -
onPagesReordered(void Function(String)?) - Called with reordered file path. -
showDeletePages(bool) =true- Show "Delete pages" icon. -
onPagesRemoved(void Function(String)?) - Called with trimmed file path. -
showAddPages(bool) =true- Show "Add pages" icon. -
onAddPagesRequested(Future?> Function()?) - Return file paths to insert. -
showAddImage(bool) =true- Show "Add image" icon. -
onAddImageRequested(Future Function()?) - Return JPEG/PNG bytes.
Styling
-
darkMode(bool) =false- Initial dark mode state. -
toolbarBackgroundColor(Color?) - Toolbar background. -
toolbarForegroundColor(Color?) - Icon/text color. -
backgroundColor(Color?) - Background during load/error.
Configuration
-
initialZoomLevel(double) =1.0- Zoom level on load. -
initialPage(int) =1- Starting page (1-indexed). -
password(String?) - Password for encrypted PDFs. -
scrollDirection(Axis) =Axis.vertical- Vertical or horizontal scrolling. -
singlePage(bool) =false- One page at a time vs continuous.
Note: If the toolbar is hidden (showToolbar: false), drive the viewer using a FlutterPdfToolkitController.
Controller reference (FlutterPdfToolkitController)
FlutterPdfToolkitController extends ChangeNotifier, so you can listen to it directly or wrap the viewer in an AnimatedBuilder / ListenableBuilder to rebuild your own UI in response to state changes.
FlutterPdfToolkitController reference
State (read-only)
Observable properties of the current document and viewer state.
-
pageNumber(int) - Current page (1-indexed). -
pageCount(int) - Total number of pages in the document. -
zoomLevel(double) - Current zoom level. -
isReady(bool) - Whether the native view has finished initializing. -
errorMessage(String?) - Non-null if document failed to load. -
bookmarks(List) - Outline/bookmarks from platform. -
searchText(String?) - The active search query, if any. -
searchResultCount(int) - Number of matches for active search. -
currentSearchResultIndex(int) - Index (1-based) of highlighted match.
Actions
Methods to control the viewer and document interaction.
Navigation
-
jumpToPage(int pageNumber)- Jump to page (1-indexed). -
nextPage()- Go to next page. -
previousPage()- Go to previous page.
Zoom
-
zoomIn([double step = 0.25])- Increase zoom by step. -
zoomOut([double step = 0.25])- Decrease zoom by step. -
resetZoom()- Reset to default zoom.
Search
- search(String text, {bool caseSensitive = false}) - Search the document.
- clearSearch() - Clear active search and highlights.
- nextSearchResult() - Jump to next match.
- previousSearchResult() - Jump to previous match.
Other
-
requestBookmarks()- Re-request bookmark/outline list. -
setDarkMode(bool enabled)- Toggle dark mode. -
getPageThumbnail(int pageNumber, {int width = 200})- Returns PNG thumbnail as Uint8List.
PdfBookmarkItem
class PdfBookmarkItem {
final String title;
final int pageNumber;
}
Password-Protected PDFs
There are two ways to supply a password:
- Pass
passworddirectly toFlutterPdfToolkit:
FlutterPdfToolkit(
source: const PdfSource.filePath('/path/to/protected.pdf'),
password: 'samplefiles',
)
- Attach a password to a
PdfSource.base64source:
FlutterPdfToolkit(
source: PdfSource.base64(base64PdfString, password: 'samplefiles'),
)
If no password is supplied (or the supplied password is incorrect), the widget shows a built-in "Password Required" dialog and prompts the user to enter the password. The dialog re-displays with an "Incorrect password" error if the entered password is rejected, and can be cancelled to abort loading the document.
Search
- Text search is supported on both Android and iOS.
- On iOS, search uses
PDFKit'snative text search. - On Android, the page text is extracted with
pdfbox-android(cached after first use) and matched case-insensitively.
Matches are highlighted on the page and the view automatically scrolls to the first/selected match.
Use
controller.search('query'),nextSearchResult(),previousSearchResult(), andclearSearch()to drive search programmatically. The toolbar reflects the active query and match count when present.
Bookmarks
- Bookmarks (PDF outline entries) are populated automatically on view creation via
requestBookmarks()and exposed throughcontroller.bookmarks. - Tapping the bookmarks icon in the toolbar opens a bottom sheet listing all bookmarks; tapping an entry jumps to that page.
- Supported on both Android and iOS - Android extracts the document outline with
pdfbox-android, while iOS reads it viaPDFKit'soutlineRoot. If a PDF has no outline/bookmarks defined,bookmarkswill be empty on either platform.
Page Thumbnails
- Tapping the thumbnails icon in the toolbar opens a grid of page previews; tapping a thumbnail jumps to that page.
- Each thumbnail is rendered natively (via
PDFKiton iOS andPdfRendereron Android) and fetched lazily as the grid is shown, then cached for the lifetime of the document. - Use
controller.getPageThumbnail(pageNumber, width: 200)to fetch a thumbnail yourself, e.g. to build a custom page picker.
Signing PDFs
Tapping the "Sign document" icon (the pen/draw icon) in the toolbar opens a built-in flow:
- A dialog where the user draws their signature with a finger/stylus (powered by
SignaturePad). - A bottom sheet showing a preview of the current page, where the user can drag and resize the signature before confirming placement.
- The signature is stamped onto the current page natively and the viewer reloads the signed copy.
onSignedis called with the path to the new file.
Hide the built-in action with showSignature: false if you want to build your own signing UI.
SignaturePad and SignaturePadController are exported so you can build a custom signature-capture UI:
final SignaturePadController controller = SignaturePadController();
final GlobalKey<SignaturePadState> padKey = GlobalKey<SignaturePadState>();
SignaturePad(key: padKey, controller: controller);
// Later, e.g. when the user taps "Done":
final Uint8List? pngBytes = await padKey.currentState?.toPngBytes();
-
toPngBytes()renders the drawn strokes to a transparent PNG. Callcontroller.clear()to reset the pad andcontroller.isEmptyto check whether anything has been drawn.
Stamp a signature (or any PNG image) onto a PDF page yourself with FlutterPdfToolkit.signPdf():
final String? signedPath = await FlutterPdfToolkit.signPdf(
sourcePath: '/path/to/document.pdf',
outputPath: '/path/to/output/signed.pdf',
signatureImageBytes: pngBytes,
pageNumber: 1, // 1-indexed
xRatio: 0.6, // left edge, as a fraction of the page width
yRatio: 0.8, // top edge, as a fraction of the page height
widthRatio: 0.3, // signature width, as a fraction of the page width
heightRatio: 0.1, // signature height, as a fraction of the page height
);
Signing parameters
Parameters for the PDF signing operation. The signature image is stamped onto the specified page at the given position and size.
Parameters
-
sourcePath(String) - Absolute file path of the PDF to sign. -
outputPath(String) - Absolute file path where the signed PDF should be written. -
signatureImageBytes(Uint8List) - PNG image to stamp onto the page, ideally with transparent background. -
pageNumber(int) - 1-indexed page number to stamp the signature onto. -
xRatio/yRatio(double) - Top-left position of signature as fraction (0.0–1.0) of page width/height. -
widthRatio/heightRatio(double) - Size of signature as fraction (0.0–1.0) of page width/height.
Returns outputPath on success, or null if signing failed. Runs natively - pdfbox-android on Android (appended to the page's content stream) and CoreGraphics on iOS (the page is redrawn into a new PDF context with the signature composited on top) - so sourcePath must be a local file path and existing vector content is preserved.
Reordering Pages
Tapping the "Reorder pages" icon (the swap icon) in the toolbar opens a built-in flow:
- A bottom sheet shows every page as a thumbnail in a grid.
- The user presses and holds a page, then drags it to a new position. Each tile shows a badge with its current position in the new order.
- Tapping "Save order" rewrites the document with the pages in their new order natively, and the viewer reloads the rearranged copy.
onPagesReorderedis called with the path to the new file.
- Hide the built-in action with
showReorder: falseif you want to build your own reordering UI.
Reorder (and optionally drop) pages yourself with FlutterPdfToolkit.reorderPages():
final String? reorderedPath = await FlutterPdfToolkit.reorderPages(
path: '/path/to/document.pdf',
outputPath: '/path/to/output/reordered.pdf',
pageOrder: [3, 1, 2], // moves page 3 to the front, drops the rest
);
Reordering parameters
Parameters for the PDF page reordering operation. Reorder pages, drop unwanted pages, or duplicate pages in the output.
Parameters
-
path(String) - Absolute file path of the PDF to reorder. -
outputPath(String) - Absolute file path where the reordered PDF should be written. -
pageOrder(List) - 1-based page numbers from source PDF, in desired output order. Omit a page number to drop that page.
Returns outputPath on success, or null if reordering failed. Runs natively - pdfbox-android on Android and PDFKit on iOS - so path must be a local file path. Use getPdfPageCount() to determine valid page numbers beforehand.
Examples
Keep pages 1, 3, 5 in order:
pageOrder: [1, 3, 5]
Reverse page order:
pageOrder: [5, 4, 3, 2, 1]
Drop page 2, keep others:
pageOrder: [1, 3, 4, 5]
Removing Pages
Tapping the "Delete pages" icon (the trash icon) in the toolbar opens a built-in flow:
- A bottom sheet shows every page as a thumbnail in a grid.
- The user taps pages to mark them for removal. Selected pages are highlighted with a checkmark.
- Tapping "Delete N pages" rewrites the document without the selected pages natively, and the viewer reloads the trimmed copy.
onPagesRemovedis called with the path to the new file.
- Hide the built-in action with
showDeletePages: falseif you want to build your own page-removal UI.
Remove pages yourself with FlutterPdfToolkit.removePages():
final String? trimmedPath = await FlutterPdfToolkit.removePages(
path: '/path/to/document.pdf',
outputPath: '/path/to/output/trimmed.pdf',
pageNumbers: [2, 4], // removes pages 2 and 4
);
Removing pages parameters
Parameters for the PDF page deletion operation. Remove unwanted pages from the document.
Parameters
-
path(String) - Absolute file path of the PDF to trim. -
outputPath(String) - Absolute file path where the trimmed PDF should be written. -
pageNumbers(List) - 1-based page numbers from source PDF to remove.
Examples
Delete pages 2 and 5:
pageNumbers: [2, 5]
Delete first page:
pageNumbers: [1]
Delete last 3 pages (10–12 of 12-page doc):
pageNumbers: [10, 11, 12]
Returns outputPath on success, or null if removal failed (including if pageNumbers covers every page in the document). Runs natively - pdfbox-android on Android and PDFKit on iOS - so path must be a local file path. Use getPdfPageCount() to determine valid page numbers beforehand.
Adding Pages
Tapping the "Add pages" icon (the document-plus icon) in the toolbar opens a built-in flow:
- A bottom sheet shows every page as a thumbnail in a grid, plus a "Start" tile. Tap a page to insert the new pages after it (or tap "Start" to insert them before page 1).
-
onAddPagesRequestedis called - your app should show its own file and/or image picker here and return the chosen local file paths, in the order they should be inserted. Return null or an empty list to cancel. - Any image files (
.jpg,.jpeg,.png,.heic,.heif,.webp,.bmp,.gif) are converted to single-page PDFs and combined with any PDF files, preserving the given order. The combined pages are inserted at the chosen position natively, and the viewer reloads the updated copy.onPagesAddedis called with the path to the new file.
- showAddPages defaults to true, but the action requires onAddPagesRequested to be provided - without it, tapping the icon shows a message that adding pages isn't configured. Set
showAddPages: falseif you want to build your own add-pages UI instead.
Insert another PDF's pages yourself with FlutterPdfToolkit.insertPages():
final String? updatedPath = await FlutterPdfToolkit.insertPages(
path: '/path/to/document.pdf',
insertPath: '/path/to/pages_to_insert.pdf',
outputPath: '/path/to/output/updated.pdf',
afterPageNumber: 2, // insert after page 2 (0 = before page 1)
);
Insert pages parameters
Parameters for the PDF page insertion operation. Insert pages from one PDF into another at a specific position.
Parameters
-
path(String) - Absolute file path of the PDF to insert pages into. -
insertPath(String) - Absolute file path of the PDF whose pages should be inserted. -
outputPath(String) - Absolute file path where the updated PDF should be written. -
afterPageNumber(int) - 1-based page number to insert after. 0 inserts before page 1. Document's page count appends at end.
Examples
Insert at beginning (before page 1):
afterPageNumber: 0
Insert after page 3:
afterPageNumber: 3
Append at end (5-page document):
afterPageNumber: 5
Returns outputPath on success, or null if insertion failed. Runs natively - pdfbox-android on Android and PDFKit on iOS - so both path and insertPath must be local file paths.
Convert images into a PDF (one page per image) with FlutterPdfToolkit.imagesToPdf():
final String? pagesPath = await FlutterPdfToolkit.imagesToPdf(
imagePaths: ['/path/to/photo1.jpg', '/path/to/photo2.png'],
outputPath: '/path/to/output/photos.pdf',
);
Parameters
-
imagePaths(List) - Absolute file paths of the images to convert, in page order. -
outputPath(String) - Absolute file path where the resulting PDF should be written.
Returns outputPath on success, or null if conversion failed. Each page is sized to match its source image. Runs natively - pdfbox-android on Android and CoreGraphics on iOS.
Adding images to a PDF
Tapping the "Add image" icon (the image-plus icon) in the toolbar opens a built-in flow:
-
onAddImageRequestedis called - your app should show its own image picker (e.g. via theimage_pickerpackage) and return the chosen image's bytes (JPEG or PNG). Returnnullto cancel. - A bottom sheet shows a preview of the current page, where the user can drag and resize the image before confirming placement.
- The image is stamped onto the current page natively and the viewer reloads the updated copy.
onImageAddedis called with the path to the new file.
-
showAddImagedefaults totrue, but the action requiresonAddImageRequestedto be provided - without it, tapping the icon shows a message that adding images isn't configured. SetshowAddImage: falseif you want to build your own add-image UI instead.
Stamp an image onto a PDF page yourself with FlutterPdfToolkit.addImageToPdf():
final String? updatedPath = await FlutterPdfToolkit.addImageToPdf(
sourcePath: '/path/to/document.pdf',
outputPath: '/path/to/output/with_image.pdf',
imageBytes: imageBytes, // JPEG or PNG bytes
pageNumber: 1, // 1-indexed
xRatio: 0.1, // left edge, as a fraction of the page width
yRatio: 0.1, // top edge, as a fraction of the page height
widthRatio: 0.3, // image width, as a fraction of the page width
heightRatio: 0.3, // image height, as a fraction of the page height
);
File paths
-
sourcePath(String) - Absolute file path of the PDF to modify. -
outputPath(String) - Absolute file path where the updated PDF should be written.
Image content
-
imageBytes(Uint8List) - JPEG or PNG image to stamp onto the page.
Page targeting
-
pageNumber(int) - 1-indexed page number to stamp the image onto.
Position and size
-
xRatio/yRatio(double) - Top-left position of the image as a fraction (0.0–1.0) of page width/height. -
widthRatio/heightRatio(double) - Size of the image as a fraction (0.0–1.0) of page width/height.
Returns outputPath on success, or null if adding the image failed. Runs natively - pdfbox-android on Android (appended to the page's content stream) and CoreGraphics on iOS (the page is redrawn into a new PDF context with the image composited on top) - so sourcePath must be a local file path and existing vector content is preserved.
Merging, Splitting, and Downloading PDFs
FlutterPdfToolkit exposes several static helper methods that don't require a viewer instance - they call straight into the native platform code via a shared method channel.
Merging PDFs
final String? mergedPath = await FlutterPdfToolkit.mergePdfs(
paths: ['/path/to/first.pdf', '/path/to/second.pdf'],
outputPath: '/path/to/output/merged.pdf',
);
if (mergedPath != null) {
// Open it in the viewer, e.g.:
// FlutterPdfToolkit(source: PdfSource.filePath(mergedPath));
}
-
paths(List) - Absolute file paths of the PDFs to merge, in the order they should appear in the output. -
outputPath(String) - Absolute file path where the merged PDF should be written.
Returns the outputPath on success, or null if merging failed (e.g. an invalid or unreadable input path). The merge is performed natively - PDFKit on iOS and pdfbox-android on Android - so all input paths must be local file paths. If a source is an asset, network URL, or in-memory bytes, write it to a temporary file first (see PDF sources).
Getting a PDF's page count
final int? pageCount = await FlutterPdfToolkit.getPdfPageCount('/path/to/document.pdf');
Returns the total number of pages, or null if the file could not be read. Useful for working out valid page ranges before calling splitPdf().
Splitting a PDF
final List<String>? files = await FlutterPdfToolkit.splitPdf(
path: '/path/to/document.pdf',
outputDirectory: '/path/to/output',
pageRanges: [
[1, 3], // pages 1-3 -> split_1.pdf
[4, 4], // page 4 -> split_2.pdf
[5, 10], // pages 5-10 -> split_3.pdf
],
);
if (files != null) {
for (final path in files) {
// e.g. open one of the resulting files in the viewer:
// FlutterPdfToolkit(source: PdfSource.filePath(path));
}
}
-
path(String) - Absolute file path of the PDF to split. -
outputDirectory(String) - Absolute path of the directory where split files are written. Directory is created automatically if it doesn't exist. -
pageRanges(List>) - One[startPage, endPage]pair per output file, 1-based and inclusive (e.g.,[1, 3]= pages 1–3). -
outputFileNamePrefix(String) -Optional prefix for output file names. Defaults to'split'. Files are named<prefix>_<n>.pdf.
Returns the list of output file paths, in the same order as pageRanges, or null if splitting failed (e.g. an invalid path or an out-of-range page number). Like mergePdfs(), this runs natively via PDFKit on iOS and pdfbox-android on Android, and path must be a local file path.
Downloading / sharing a PDF
final bool success = await FlutterPdfToolkit.downloadPdf(
sourcePath: '/path/to/merged.pdf',
fileName: 'merged_document.pdf',
);
-
sourcePath(String) - Absolute path of the PDF file to save or share. -
fileName(String) - Suggested file name for the saved or shared copy.
On Android, the file is copied into the device's public Downloads folder under fileName.
On iOS, the system share sheet is opened so the user can save the file to Files, AirDrop it, etc.
Returns true if the save/share action completed successfully, false otherwise.
Zoom
- Pinch-to-zoom is supported on both platforms via the built-in scroll/zoom view.
- Double-tapping the page toggles between the default zoom level and 2x zoom, centered on the tap location, on both Android and iOS.
-
controller.zoomIn(),zoomOut(), andresetZoom()drive zoom programmatically; the toolbar's zoom buttons call these directly.
Dark Mode
-
darkModesets the initial state of the native viewer's color scheme. - The built-in toolbar includes a sun/moon toggle (
showThemeToggle) that callscontroller.setDarkMode(...)and rebuilds the toolbar's icon. -
controller.setDarkMode(bool enabled)can be called at any time - including before the native view is ready, in which case it is applied once the view finishes initializing. - Dark mode only affects the PDF viewer's chrome/background at the native level; it does not alter the content of the PDF itself.
Limitations
- Only Android and iOS are currently supported - there is no web, desktop, or macOS implementation.
- Search is case-insensitive on both platforms; advanced query syntax (regex, whole-word, etc.) is not supported.
Conclusion
Building PDF functionality in Flutter shouldn't require multiple plugins, complex native integrations, or performance trade-offs. With flutter_pdf_toolkit, you get a powerful all-in-one solution for viewing, searching, editing, signing, and managing PDFs using native rendering on Android and iOS. If your app works with documents, this package can help you deliver a faster, smoother, and more professional user experience with minimal effort. 🚀
Top comments (0)