Programmatically manage PDF annotations in Flutter

Nutrient Flutter SDK offers several methods to programmatically get, add, and remove annotations. Since version 4.2.0, we’ve replaced Instant JSON with annotation model classes.

For adding and removing annotations, backward compatibility is maintained, so you can use both annotation model classes and Instant JSON. However, for retrieving annotations, the getAnnotations method only supports annotation model classes.

To get annotations in Instant JSON format, use the PdfDocument.getAnnotationsAsJSON or PdfDocument.getAllUnsavedAnnotations methods.

Method
Description
getAnnotations(int pageIndex, AnnotationType type) Gets all annotations on the given page index of the given type. List of all supported annotation types.
getUnsavedAnnotations() Gets all the unsaved annotations from the entire document.
addAnnotation(dynamic annotation) Adds the given annotation to the document.
addAnnotations(List<Annotation> annotations) Adds the given list of annotations. This does not trigger an annotationCreated event.
removeAnnotation(dynamic annotation) Removes the given annotation from the document. If the given annotation doesn’t exist, this method does nothing.

Getting all annotations

The example below shows how to get all annotations on the first page of a document:

List<Annotation> allAnnotations = await pdfDocument.getAnnotations(0, AnnotationType.all);
print(allAnnotations);

Removing all annotations

The example below shows how to remove an array of annotations from a document:

List<Annotation> allAnnotations = await pdfDocument.getAnnotations(0, AnnotationType.all);
print(allAnnotations);

// Make sure at least one annotation exists in the document.
// Remove the first annotation.
await pdfDocument.removeAnnotation(allAnnotations[0]);
print(allAnnotations);

Adding annotations

The examples below show how to programmatically create different types of annotations in your Flutter PDF documents using Nutrient.

API reference

// Create a new link annotation with a URL.
final linkAnnotation = LinkAnnotation(
    id: 'link-annotation-1',
    bbox: [50.0, 700.0, 200.0, 30.0],
    createdAt: '2025-01-08T12:08:57+03:00',
    action: UriAction(
      uri: 'https://nutrient.io',
    ),
    pageIndex: 0,
    creatorName: 'Nutrient Flutter',
  );

// Add the annotation to the document.
await document.addAnnotation(linkAnnotation);

Highlight annotations

API reference

// Create a highlight annotation.
final highlightAnnotation =   HighlightAnnotation(
    id: 'highlight-annotation-1',
    bbox: [50.0, 450.0, 200.0, 20.0],
    createdAt: '2025-01-07T16:49:18+03:00',
    color: const Color(0xFFFFEB3B),
    rects: [
      [50.0, 450.0, 200.0, 470.0],
    ],
    opacity: 0.5,
    pageIndex: 0,
    creatorName: 'Nutrient Flutter',
  );

await document.addAnnotation(highlightAnnotation);

Free text annotations

API reference

// Create a free text annotation.
final freeTextAnnotation =   FreeTextAnnotation(
    id: 'freetext-annotation-1',
    bbox: [50.0, 650.0, 200.0, 50.0],
    createdAt: '2025-01-07T16:46:01+03:00',
    text: TextContent(
      format: TextFormat.plain,
      value: 'This is a free text annotation',
    ),
    fontColor: const Color(0xFF000000),
    fontSize: 20,
    font: 'sans-serif',
    pageIndex: 0,
    creatorName: 'Nutrient Flutter',
    backgroundColor: const Color(0xFFFF0000),
    horizontalTextAlign: HorizontalTextAlignment.left,
    verticalAlign: VerticalAlignment.top,
  );

await document.addAnnotation(freeTextAnnotation);

Ink annotations

API reference

// Create an ink annotation with drawing points.
final inkAnnotation =  InkAnnotation(
      id: 'ink-annotation-1',
      bbox: [267.4, 335.1, 97.2, 10.3],
      createdAt: '2025-01-06T16:36:59+03:00',
      lines: InkLines(
        points: [
          [
            [269.4, 343.4],
            [308.4, 341.7],
            [341.2, 339.6],
            [358.8, 339.6],
            [360.9, 339.2],
            [362.6, 338.8],
            [361.7, 337.1],
          ]
        ],
        intensities: [
          [1.0, 0.43, 0.64, 0.83, 0.98, 0.99, 0.97]
        ],
      ),
      lineWidth: 4,
      opacity: 1.0,
      flags: [AnnotationFlag.print],
      creatorName: 'Nutrient Flutter',
      isDrawnNaturally: false,
      strokeColor: const Color(0xFF2492FB),
      pageIndex: 0);

await document.addAnnotation(inkAnnotation);

Note annotations

API reference

// Create a note annotation.
final noteAnnotation =  NoteAnnotation(
    id: 'note-annotation-1',
    bbox: [400.0, 450.0, 32.0, 32.0],
    createdAt: '2025-01-07T16:49:18+03:00',
    text: TextContent(value: 'This is a note', format: TextFormat.plain),
    color: const Color(0xFFFF9800),
    pageIndex: 0,
    creatorName: 'Nutrient Flutter',
  );

await document.addAnnotation(noteAnnotation);

Stamp annotations

API reference

// Create a stamp annotation
final stampAnnotation =  StampAnnotation(
      id: 'stamp-annotation-1',
      bbox: [50.0, 650.0, 50.0, 50.0],
      stampType: StampType.approved,
      pageIndex: 0);

await document.addAnnotation(stampAnnotation);

Image annotations

API reference

// Example of a square annotation.
 final imageAnnotation =  ImageAnnotation(
    id: 'image-annotation-1',
    bbox: [300.0, 750.0, 100.0, 100.0],
    createdAt: '2025-01-08T12:08:57+03:00',
    imageAttachmentId:
        '303c4baa3d6adfcb12cd71e7060d6714850fa9c5404270fde637e43606352580',
    pageIndex: 0,
    creatorName: 'Nutrient Flutter',
    attachment: const AnnotationAttachment(
        id: '303c4baa3d6adfcb12cd71e7060d6714850fa9c5404270fde637e43606352580',
		  contentType: 'image/jpeg',
        binary:
            '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',
    ),
  )

await document.addAnnotation(imageAnnotation);

Adding multiple annotations

For better performance, add multiple annotations in a single operation:

final annotations = [
  noteAnnotation,
  highlightAnnotation,
  inkAnnotation,
];

await document.addAnnotations(annotations);

This won’t trigger any annotationsCreated events. If you need to listen to these events, add each annotation separately using the addAnnotation method.