Configure PDF annotations in Android

Every annotation of a document has properties specific to its type. For example, ink annotations have a color property as well as a line width, whereas note annotations carry an icon property. When creating annotations using any of the annotation tools inside the annotation creation toolbar, newly created annotations will have their properties set to default values.

The configuration for each annotation type is governed by a set of interfaces extending AnnotationConfiguration. Annotation configuration controls allowed values, default values, and whether or not a property is editable. For every annotation type that can be created using the annotation creation toolbar, one such configuration interface exists. For example, configuration for ink annotations is provided by the InkAnnotationConfiguration. An extensive list of supported annotation configuration interfaces can be found below.

Annotation configuration

Annotation configuration for a specific annotation type extends various property-specific configuration interfaces — one for every annotation property that is supported by the specific annotation type.

Here’s a list of available property configuration interfaces that can be implemented by annotation configuration:

Interface Description
AnnotationAggregationStrategyConfiguration Provides annotation aggregation strategy configuration.
AnnotationAlphaConfiguration Provides alpha configuration.
AnnotationBorderStyleConfiguration Provides border style configuration.
AnnotationColorConfiguration Provides foreground color configuration.
AnnotationFillColorConfiguration Provides fill color configuration.
AnnotationFontConfiguration Provides configuration for free-text annotations font.
AnnotationLineEndsConfiguration Provides line end type configuration.
AnnotationNoteIconConfiguration Provides note annotation icon configuration.
AnnotationOutlineColorConfiguration Provides outline color configuration.
AnnotationOverlayTextConfiguration Provides configuration for overlay text of redaction annotations.
AnnotationPreviewConfiguration Provides configuration regarding the inspector preview.
AnnotationTextSizeConfiguration Provides text size configuration.
AnnotationThicknessConfiguration Provides thickness configuration.

To simplify the implementation of annotation configuration, Nutrient ships with ready-to-use builders for all supported annotation types and annotation tools that can be created by factory methods in the corresponding annotation configuration interfaces:

Customizing annotation configuration

Annotation configuration can be set for each annotation type or tool via AnnotationConfigurationRegistry#put(). An instance of AnnotationConfigurationRegistry can be retrieved via PdfFragment#getAnnotationConfiguration(). The annotation creation UI (toolbar, inspector, and note editor) first queries configuration for the active annotation tool. If no configuration is set for this annotation tool, the configuration for the underlying annotation type (retrieved via AnnotationTool#toAnnotationType()) is used. The annotation editing toolbar always uses configuration for the selected annotation type.

For example, this is how you override configuration for ink annotations:

override fun onDocumentLoaded(document: PdfDocument) {
    ...

    pdfFragment?.annotationConfiguration?.put(
        AnnotationType.INK,
        InkAnnotationConfiguration.builder(context)
            // Here you can specify which color is used when creating ink annotations.
            .setDefaultColor(Color.rgb(252, 237, 140))
            // Here you can specify which colors are going to be available in the color picker.
            .setAvailableColors(
                listOf(
                    Color.rgb(244, 67, 54), // RED
                    Color.rgb(139, 195, 74), // LIGHT GREEN
                    Color.rgb(33, 150, 243), // BLUE
                    Color.rgb(252, 237, 140), // YELLOW
                    Color.rgb(233, 30, 99) // PINK
                )
            )

            // Here you can modify the thickness picker range and default thickness.
            .setDefaultThickness(5F)
            .setMinThickness(1F)
            .setMaxThickness(20F)

            // When `true`, attributes like the default color are always used as the default when creating annotations.
            // When `false`, the last edited value is used. The value from configuration is used only when creating an annotation for the first time.
            .setForceDefaults(true)

            // Build the configuration.
            .build()
    )
}
@Override
public void onDocumentLoaded(@NonNull PdfDocument document) {
    ...
    getPdfFragment().getAnnotationConfiguration().put(
        AnnotationType.INK,
        InkAnnotationConfiguration.builder(this)
            // Here you can specify which color is used when creating ink annotations.
            .setDefaultColor(Color.rgb(252, 237, 140))
            // Here you can specify which colors are going to be available in the color picker.
            .setAvailableColors(
                Arrays.asList(
                    Color.rgb(244, 67, 54), // RED
                    Color.rgb(139, 195, 74), // LIGHT GREEN
                    Color.rgb(33, 150, 243), // BLUE
                    Color.rgb(252, 237, 140), // YELLOW
                    Color.rgb(233, 30, 99) // PINK
                )
            )

            // Here you can modify the thickness picker range and default thickness.
            .setDefaultThickness(5)
            .setMinThickness(1)
            .setMaxThickness(20)

           // When `true`, attributes like the default color are always used as the default when creating annotations.
           // When `false`, the last edited value is used. The value from configuration is used only when creating an annotation for the first time.
            .setForceDefaults(true)

            // Build the configuration.
            .build()
    );
}

Annotation tools can also have specified variants. This allows you to have the same annotation tools with different presets. To learn more, refer to the Annotation Tool Variants section.

For a complete example of how to customize annotation configuration, see AnnotationConfigurationExample inside the Catalog app.

Disabling annotation properties

To remove a certain property from all annotation types that support it, disable the property in annotation configuration for all annotation types.

For example, to disable the annotation note option in the annotation editing toolbar, the ANNOTATION_NOTE property must be removed from the annotation configuration of all types that support annotation notes:

override fun onDocumentLoaded(document: PdfDocument) {
    ...
    val annotationConfigurationRegistry = pdfFragment.annotationConfiguration

    val annotationTypesWithNotes = listOf(
        AnnotationType.INK,
        AnnotationType.LINE,
        AnnotationType.POLYLINE,
        AnnotationType.SQUARE,
        AnnotationType.CIRCLE,
        AnnotationType.POLYGON,
        AnnotationType.FREETEXT,
        AnnotationType.UNDERLINE,
        AnnotationType.SQUIGGLY,
        AnnotationType.STRIKEOUT,
        AnnotationType.HIGHLIGHT,
        AnnotationType.STAMP,
        AnnotationType.FILE,
        AnnotationType.REDACT)

    // We'll disable the `ANNOTATION_NOTE` property for every annotation type that supports notes.
    for (annotationType in annotationTypesWithNotes) {
        annotationConfigurationRegistry.put(
            annotationType,
            AnnotationConfiguration.builder(this, annotationType)
                .disableProperty(AnnotationProperty.ANNOTATION_NOTE)
                .build())
    }
    ...
}
@Override
public void onDocumentLoaded(@NonNull PdfDocument document) {
    ...
    AnnotationConfigurationRegistry annotationConfigurationRegistry = getPdfFragment().getAnnotationConfiguration();

    List<AnnotationType> annotationTypesWithNotes = Arrays.asList(
        AnnotationType.INK,
        AnnotationType.LINE,
        AnnotationType.POLYLINE,
        AnnotationType.SQUARE,
        AnnotationType.CIRCLE,
        AnnotationType.POLYGON,
        AnnotationType.FREETEXT,
        AnnotationType.UNDERLINE,
        AnnotationType.SQUIGGLY,
        AnnotationType.STRIKEOUT,
        AnnotationType.HIGHLIGHT,
        AnnotationType.STAMP,
        AnnotationType.FILE,
        AnnotationType.REDACT);

    // We'll disable the `ANNOTATION_NOTE` property for every annotation type that supports notes.
    for (AnnotationType annotationType : annotationTypesWithNotes) {
        annotationConfigurationRegistry.put(
            annotationType,
            AnnotationConfiguration.builder(this, annotationType)
                .disableProperty(AnnotationProperty.ANNOTATION_NOTE)
                .build());
    }
    ...
}

Ink aggregation strategy

By default, ink drawing is automatically split into annotations based on the timing of strokes and the distance between drawn points. This feature can be controlled via AnnotationAggregationStrategyConfiguration, which is currently supported for ink annotations.

If you want to have ink strokes merged into a single annotation instead, change the default aggregation strategy to AnnotationAggregationStrategy#MERGE_IF_POSSIBLE. This will aggregate all compatible ink strokes into a single annotation, i.e. strokes that have the same color, thickness, and alpha value:

pdfFragment?.annotationConfiguration.put(
    AnnotationType.INK,
    InkAnnotationConfiguration.builder(context)
        // PSPDFKit 5.3+ defaults to `AUTOMATIC`.
        // `MERGE_IF_POSSIBLE` matches the older version's behavior.
        .setAnnotationAggregationStrategy(AnnotationAggregationStrategy.MERGE_IF_POSSIBLE)
        .build()
)
getPdfFragment().getAnnotationConfiguration().put(
    AnnotationType.INK,
    InkAnnotationConfiguration.builder(this)
        // PSPDFKit 5.3+ defaults to `AUTOMATIC`.
        // `MERGE_IF_POSSIBLE` matches the older version's behavior.
        .setAnnotationAggregationStrategy(AnnotationAggregationStrategy.MERGE_IF_POSSIBLE)
        .build()
);