A Flutter plugin for opening and annotating PDF files natively on iOS and Android.
Presents a full-screen native editor with freehand drawing, highlighting, image stamping, erasing, undo, color picker, and pen-size presets β then saves the annotated PDF back to a file path of your choice.
| Feature | Description |
|---|---|
| Freehand pen | Draw with custom colour and stroke width |
| Highlighter | Semi-transparent highlight with adjustable opacity |
| Image stamps | Place signatures, logos, or images β resize, accept, or delete |
| Eraser | Remove individual annotations |
| Undo | Step back through all annotation types |
| Save | Write the annotated PDF to any writable path |
| Share | Share via the native share sheet |
| Multiple sources | Open from file path, raw bytes, URL, or Flutter asset |
| Typed results | Distinguish success, cancellation, and errors without try/catch |
| Localization | Native UI in English π¬π§, Arabic πΈπ¦, Spanish πͺπΈ, and Portuguese π΅πΉ |
| Android | iOS |
|---|---|
| API 21+ | iOS 14+ |
dependencies:
flutter_pdf_annotations: ^1.3.0flutter pub getNo extra permissions or setup needed for paths inside the app's own directories (getExternalFilesDir, filesDir).
If you plan to download PDFs from the internet using openFromUrl, make sure your AndroidManifest.xml includes:
<uses-permission android:name="android.permission.INTERNET"/>If you allow the user to pick images for stamping, add to ios/Runner/Info.plist:
<key>NSPhotoLibraryUsageDescription</key>
<string>Select images to insert into PDF annotations</string>import 'package:flutter_pdf_annotations/flutter_pdf_annotations.dart';
final result = await FlutterPdfAnnotations.openPDF(
filePath: '/path/to/document.pdf',
);
if (result.isSuccess) {
print('Saved to: ${result.savedPath}');
} else if (result.isCancelled) {
print('User cancelled');
} else {
print('Error: ${result.error}');
}final result = await FlutterPdfAnnotations.openPDF(
filePath: '/path/to/document.pdf',
savePath: '/path/to/annotated.pdf',
config: PDFAnnotationConfig(
title: 'Review Contract',
initialPenColor: Colors.red,
initialHighlightColor: Colors.yellow.withOpacity(0.5),
initialStrokeWidth: 3.0,
initialPage: 2, // open at page 3 (zero-based)
locale: PdfLocale.arabic, // force Arabic UI
),
);final signatureBytes = await File('signature.png').readAsBytes();
final result = await FlutterPdfAnnotations.openPDF(
filePath: '/path/to/document.pdf',
config: PDFAnnotationConfig(
title: 'Sign Document',
imagesToInsert: [signatureBytes],
),
);final result = await FlutterPdfAnnotations.openFromUrl(
url: 'https://example.com/document.pdf',
headers: {
'Authorization': 'Bearer your_token',
'X-Custom-Header': 'value',
},
config: PDFAnnotationConfig(title: 'Remote PDF'),
);final Uint8List pdfBytes = /* from network, database, etc. */;
final result = await FlutterPdfAnnotations.openFromBytes(
bytes: pdfBytes,
config: PDFAnnotationConfig(title: 'In-Memory PDF'),
);// Declare in pubspec.yaml:
// flutter:
// assets:
// - assets/sample.pdf
final result = await FlutterPdfAnnotations.openFromAsset(
assetPath: 'assets/sample.pdf',
);The native editor UI is automatically displayed in the device language. You can also force a specific language via PDFAnnotationConfig.locale.
| Enum | Language | Flag |
|---|---|---|
PdfLocale.english |
English (default fallback) | π¬π§ |
PdfLocale.arabic |
Arabic | πΈπ¦ |
PdfLocale.spanish |
Spanish | πͺπΈ |
PdfLocale.portuguese |
Portuguese | π΅πΉ |
// Auto-detect from device (recommended)
PDFAnnotationConfig()
// Force a specific language
PDFAnnotationConfig(locale: PdfLocale.arabic)
PDFAnnotationConfig(locale: PdfLocale.spanish)
PDFAnnotationConfig(locale: PdfLocale.portuguese)Any unsupported device locale falls back to English automatically.
| Method | Description |
|---|---|
openPDF({filePath, savePath?, config?}) |
Open a PDF from a local file path |
openFromBytes({bytes, savePath?, config?}) |
Open a PDF from Uint8List bytes |
openFromUrl({url, headers?, savePath?, config?}) |
Download and open a PDF from a URL |
openFromAsset({assetPath, savePath?, config?}) |
Open a PDF bundled as a Flutter asset |
All methods return Future<PdfAnnotationResult>.
| Property | Type | Description |
|---|---|---|
isSuccess |
bool |
true when the user saved β savedPath is non-null |
savedPath |
String? |
Output file path |
isCancelled |
bool |
true when the user dismissed without saving |
isError |
bool |
true when an error occurred |
error |
String? |
Error description |
| Parameter | Type | Default | Description |
|---|---|---|---|
title |
String? |
'PDF Annotations' |
Editor navigation bar title |
initialPenColor |
Color? |
Red | Starting pen colour |
initialHighlightColor |
Color? |
Yellow (50% opacity) | Starting highlight colour (include alpha) |
initialStrokeWidth |
double? |
8.0 (M) |
Starting stroke width β 3.0 (S), 8.0 (M), 18.0 (L) |
imagesToInsert |
List<Uint8List>? |
null |
Images available for stamping (PNG, JPEG, etc.) |
initialPage |
int |
0 |
Zero-based page index to open at |
locale |
PdfLocale? |
device locale | Editor UI language β see Localization |
enum PdfLocale { english, arabic, spanish, portuguese }Pull requests are welcome. Please open an issue first to discuss the change.
MIT Β© 2025-2026 Mohamed Ghoneim