Annotation Defaults

Every annotation of a document has properties specific to its type. For example, ink annotations have a color property as well as a text size, 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 defaults for each annotation type are provided by classes implementing AnnotationDefaultsProvider. Annotation defaults control allowed values, default values, and whether or not a property is editable. For example, the defaults for ink annotations are provided by the InkAnnotationDefaultsProvider. For every annotation type that can be created using the annotation creation toolbar, one such defaults provider exists. An extensive list of available annotation defaults providers can be found below.

Annotation Property Defaults

Every annotation defaults provider for a specific annotation type extends and implements various property-specific default provider interfaces — one for every annotation property that is supported by the specific annotation type.

Here’s a list of available property specific default providers that can be implemented by annotation default providers:

Interface Description
AnnotationDefaultsBorderStyleProvider Provides border style settings.
AnnotationDefaultsColorProvider Provides foreground color settings.
AnnotationDefaultsFillColorProvider Provides fill color settings.
AnnotationDefaultsLineEndTypeProvider Provides line end type settings.
AnnotationDefaultsNoteIconProvider Provides note annotation icon settings.
AnnotationDefaultsPreviewProvider Provides settings regarding the inspector preview.
AnnotationDefaultsStampProvider Provides stamp annotation settings.
AnnotationDefaultsTextSizeProvider Provides text size settings.
AnnotationDefaultsThicknessProvider Provides thickness settings.
AnnotationDefaultsAlphaProvider Provides alpha settings.
AnnotationAggregationStrategyDefaultsProvider Provides annotation aggregation strategy settings.

To simplify the implementation of annotation defaults providers, PSPDFKit provides ready-to-use implementations for all supported annotation types and annotation tools:

Custom Annotation Defaults

Custom annotation defaults providers can be set for each annotation type or tool via AnnotationDefaultsManager#setAnnotationDefaultsProvider(). An instance of AnnotationDefaultsManager can be retrieved via PdfFragment#getAnnotationDefaults(). The annotation creation UI (toolbar, inspector, and note editor) first queries defaults for the active annotation tool. If no provider is set for this annotation tool, the provider for the underlying annotation type (retrieved via AnnotationTool#toAnnotationType()) is used. The annotation editing toolbar always uses defaults for the selected annotation type.

For example, this is how you override defaults for ink annotations using our existing defaults provider:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
override fun onDocumentLoaded(document: PdfDocument) {
    ...
    pdfFragment?.annotationDefaults.setAnnotationDefaultsProvider(AnnotationType.INK, object : InkAnnotationDefaultsProvider(context) {
        /** Here you can specify which color is used when creating ink annotations. */
        override fun getDefaultColor() = Color.rgb(252, 237, 140)

        /** Here you can specify which colors are going to be available in the color picker. */
        override fun getAvailableColors() = intArrayOf(
            // RED
            Color.rgb(244, 67, 54),
            // LIGHT GREEN
            Color.rgb(139, 195, 74),
            // BLUE
            Color.rgb(33, 150, 243),
            // YELLOW
            Color.rgb(252, 237, 140),
            // PINK
            Color.rgb(233, 30, 99))

        // Here you can modify the thickness picker range and default thickness.
        override fun getDefaultThickness() = 5f
        override fun getMinThickness() = 1f
        override fun getMaxThickness() = 20f

        /** Disable the preview in the annotation inspector for ink annotations. */
        override fun isPreviewEnabled() = false

        /**
        * When true, attributes like the default color are always used as the default when creating annotations.
        * When false, the last edited value is used. Note that the value from the defaults provider is used only
        * when creating an annotation for the first time.
        */
        override fun forceDefaults() = true
    })
}
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
@Override
public void onDocumentLoaded(@NonNull PdfDocument document) {
    ...
    getPdfFragment().getAnnotationDefaults().setAnnotationDefaultsProvider(AnnotationType.INK, new InkAnnotationDefaultsProvider(this) {
        /** Here you can specify which color is used when creating ink annotations. */
        @Override
        public int getDefaultColor() {
            return Color.rgb(252, 237, 140);
        }

        /** Here you can specify which colors are going to be available in the color picker. */
        @NonNull
        @Override
        public int[] getAvailableColors() {
            return new int[]{
                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.
        @Override
        public float getDefaultThickness() {
            return 5;
        }

        @Override
        public float getMinThickness() {
            return 1;
        }

        @Override
        public float getMaxThickness() {
            return 20;
        }

        /** Disable the preview in the annotation inspector for ink annotations. */
        @Override
        public boolean isPreviewEnabled() {
            return false;
        }

        /**
       	* When true, attributes like the default color are always used as the default when creating annotations.
        * When false, the last edited value is used. Note that the value from the defaults provider is used only
        * when creating an annotation for the first time.
        */
        @Override
        public boolean forceDefaults() {
            return true;
        }
    });
}

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

Disabling Annotation Properties

To remove a certain property from all providers that support it, the recommended way is by extending the annotation defaults providers and removing the property.

For example, to disable the annotation note option in the annotation editing toolbar, the ANNOTATION_NOTE property must be removed from all the annotation defaults providers that support it:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
override fun onDocumentLoaded(document: PdfDocument) {
    ...
    val annotationDefaultsManager = pdfFragment!!.annotationDefaults

    // For every annotation type supporting the ANNOTATION_NOTE property, we are going to implement a custom annotation
    // defaults provider class with all the supported properties except for ANNOTATION_NOTE.
    annotationDefaultsManager.setAnnotationDefaultsProvider(AnnotationType.INK, CustomInkAnnotationDefaultsProvider(this))
    annotationDefaultsManager.setAnnotationDefaultsProvider(AnnotationType.LINE, CustomLineAnnotationDefaultsProvider(this))
    annotationDefaultsManager.setAnnotationDefaultsProvider(AnnotationType.SQUARE, CustomShapeAnnotationDefaultsProvider(this, AnnotationTool.SQUARE))
    ...
}
...

class CustomInkAnnotationDefaultsProvider internal constructor(context: Context) : InkAnnotationDefaultsProvider(context) {
    override fun getSupportedProperties(): EnumSet<AnnotationProperty> {
        val supportedProperties = super.getSupportedProperties()
        supportedProperties.remove(AnnotationProperty.ANNOTATION_NOTE)
        return supportedProperties
    }
}

class CustomLineAnnotationDefaultsProvider internal constructor(context: Context) : LineAnnotationDefaultsProvider(context) {
    override fun getSupportedProperties(): EnumSet<AnnotationProperty> {
        val supportedProperties = super.getSupportedProperties()
        supportedProperties.remove(AnnotationProperty.ANNOTATION_NOTE)
        return supportedProperties
    }
}

class CustomShapeAnnotationDefaultsProvider internal constructor(context: Context, annotationTool: AnnotationTool) : ShapeAnnotationDefaultsProvider(context, annotationTool) {
    override fun getSupportedProperties(): EnumSet<AnnotationProperty> {
        val supportedProperties = super.getSupportedProperties()
        supportedProperties.remove(AnnotationProperty.ANNOTATION_NOTE)
        return supportedProperties
    }
}
...
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
@Override
public void onDocumentLoaded(@NonNull PdfDocument document) {
    ...
    AnnotationDefaultsManager annotationDefaultsManager = getPdfFragment().getAnnotationDefaults();

   // For every annotation type supporting the ANNOTATION_NOTE property, we are going to implement a custom annotation
   // defaults provider class with all the supported properties except for ANNOTATION_NOTE.
    annotationDefaultsManager.setAnnotationDefaultsProvider(AnnotationType.INK, new CustomInkAnnotationDefaultsProvider(this));
    annotationDefaultsManager.setAnnotationDefaultsProvider(AnnotationType.LINE, new CustomLineAnnotationDefaultsProvider(this));
    annotationDefaultsManager.setAnnotationDefaultsProvider(AnnotationType.SQUARE, new CustomShapeAnnotationDefaultsProvider(this, AnnotationTool.SQUARE));
    ...
}
...

public static class CustomInkAnnotationDefaultsProvider extends InkAnnotationDefaultsProvider {
    CustomInkAnnotationDefaultsProvider(@NonNull Context context) {
        super(context);
    }

    @NonNull
    @Override
    public EnumSet<AnnotationProperty> getSupportedProperties() {
        EnumSet<AnnotationProperty> supportedProperties = super.getSupportedProperties();
        supportedProperties.remove(AnnotationProperty.ANNOTATION_NOTE);
        return supportedProperties;
    }
}

public static class CustomLineAnnotationDefaultsProvider extends LineAnnotationDefaultsProvider {
    CustomLineAnnotationDefaultsProvider(@NonNull Context context) {
        super(context);
    }

    @NonNull
    @Override
    public EnumSet<AnnotationProperty> getSupportedProperties() {
        EnumSet<AnnotationProperty> supportedProperties = super.getSupportedProperties();
        supportedProperties.remove(AnnotationProperty.ANNOTATION_NOTE);
        return supportedProperties;
    }
}

public static class CustomShapeAnnotationDefaultsProvider extends ShapeAnnotationDefaultsProvider {
    CustomShapeAnnotationDefaultsProvider(@NonNull Context context, @NonNull AnnotationTool annotationTool) {
        super(context, annotationTool);
    }

    @NonNull
    @Override
    public EnumSet<AnnotationProperty> getSupportedProperties() {
        EnumSet<AnnotationProperty> supportedProperties = super.getSupportedProperties();
        supportedProperties.remove(AnnotationProperty.ANNOTATION_NOTE);
        return supportedProperties;
    }
}
...

ℹ️ Note: For the full list of annotation defaults providers supporting the ANNOTATION_NOTE property, check out CustomAnnotationDefaultsManagerExample in the Catalog app.

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 AnnotationAggregationStrategyDefaultsProvider, 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:

Copy
1
2
3
4
5
pdfFragment?.annotationDefaults.setAnnotationDefaultsProvider(AnnotationType.INK, object : InkAnnotationDefaultsProvider(context) {
    // PSPDFKit 5.3+ defaults to AUTOMATIC.
    // MERGE_IF_POSSIBLE matches the older version's behavior.
   override fun getAggregationStrategy() = AnnotationAggregationStrategy.MERGE_IF_POSSIBLE
})
Copy
1
2
3
4
5
6
7
8
9
getPdfFragment().getAnnotationDefaults().setAnnotationDefaultsProvider(AnnotationType.INK, new InkAnnotationDefaultsProvider(this) {
    @NonNull
    @Override
    public AnnotationAggregationStrategy getAggregationStrategy() {
        // PSPDFKit 5.3+ defaults to AUTOMATIC.
        // MERGE_IF_POSSIBLE matches the older version's behavior.
        return AnnotationAggregationStrategy.MERGE_IF_POSSIBLE;
    }
});