Nutrient Android SDK 11.3 release notes

RSS

26 Mar 2026

Nutrient Android SDK 11.3 unifies annotation creation and editing into a single “annotating” mode. The previously separate annotation creation and annotation editing modes — each with their own controllers, listeners, and inspector controllers — are now handled by a unified set of APIs. As part of this change, the AnnotationEditingToolbar has been removed and replaced by a popup toolbar that appears directly next to the selected annotation.

This is a breaking change. Refer to the migration guide below for details on updating your code.

This release contains several fixes and enhancements. For the full list of changes, refer to our changelog.

UI improvements

  • Icons have been added to the annotation popup toolbar with improved UI styling and animations.
  • Icons have been added to the text selection and long-press popup toolbars.
  • Touch animations have been added to text selection handles with scale-up on press, finger tracking during drag, and smooth return animation on release.
  • The magnifier view has been improved with an animation and a higher position for better visibility.
  • Annotation toolbar buttons now show a tooltip on long-press instead of a toast.
  • TextSelectionToolbar and the isTextSelectionPopupToolbarEnabled configuration option have been deprecated. The popup toolbar is now the only supported text selection toolbar; the legacy toolbar will be removed in a future version.

Bug fixes

This release addresses issues in both the user interface and underlying model layer.

UI

  • Fixed DocumentView position and popup toolbar placement breaking after exiting form or content editing mode.
  • Fixed a crash when tapping form elements due to uninitialized property access in ExtractedFormElementView.
  • Fixed a race condition where the low-resolution page bitmap cache could briefly show an annotation with outdated properties.
  • Fixed an issue where dragging after long-pressing to select text would scroll the page, causing the popup toolbar to flicker.
  • Fixed an issue where erasing a pending ink annotation could remain partially visible until rendering catches up.
  • Fixed annotation selection not working after dismissing text selection in annotation creation mode.
  • Fixed cursor positioning when tapping in empty space to the right of a line’s text in content editing, which incorrectly placed the cursor at the beginning of the next line instead of the end of the tapped line.
  • Fixed form editing mode activating when tapping an annotation that overlaps a form field.
  • Fixed freezes when erasing ink annotations at high zoom levels by clamping eraser radius handling and sampling work.
  • Fixed the measurement scale FAB not showing when selecting a measurement annotation.
  • Fixed pinch-to-zoom accidentally triggering text selection in annotation mode.
  • Fixed space character input occasionally being swallowed during content editing on Samsung devices.
  • Fixed text selection handles not allowing shortening of the selection by dragging inward.
  • Fixed the document jumping back to the first page after a content editing save operation when the restoreLastViewedPage option is enabled.
  • Fixed an issue where tapping a free text annotation to start editing would trigger drag detection and hide the keyboard and UI.
  • Fixed ANRs caused by smart zoom text lookup blocking the main thread during double-tap.
  • Fixed drawable providers not rendering on scrollable thumbnail bar mode.
  • Fixed search highlights and annotation drawables disappearing after page recycling.
  • Fixed IME extract mode (fullscreen editing) not activating for content editing in landscape mode.
  • Fixed the thumbnail bar not being displayed after a document editing action.
  • Fixed the thumbnail bar showing the wrong page after saving a content editing session.
  • Fixed a potential rare crash in the thumbnail bar with recycled bitmaps when Compose abandons a composition during rapid scrolling.
  • Fixed an issue with page rendering moving incorrectly at very high zoom levels by limiting default max zoom.

Model

  • Improved memory pressure log messages to be less alarming and more informative.
  • Improved paragraph detection for content editing on PDF/UA documents.
  • Readded the FreeTextAnnotation.resizeToFitText() Kotlin extension function that was accidentally removed in 10.8.0. See FreeTextAnnotationUtils changes for details.
  • Fixed a crash caused by ClosedByInterruptException during document opening when the IO thread is interrupted.
  • Fixed a regression where adjusting the opacity slider on certain annotations didn’t correctly update the fill opacity (for example, on highlight annotations).
  • Fixed an issue where content editing didn’t update the modification date of the PDF.
  • Fixed an issue where repeated redactions on certain image-based PDFs could cause the page colors to toggle or appear inverted.
  • Fixed content editing mismatch warnings to show the original PDF font name instead of the substituted fallback font.

The new annotation popup toolbar (which replaces the removed AnnotationEditingToolbar) can be customized via the OnPreparePopupToolbarListener. This listener now provides callbacks for all popup toolbar types:

  • onPrepareAnnotationPopupToolbar(AnnotationPopupToolbar)New, called when the annotation popup toolbar is about to be displayed. AnnotationPopupToolbar is a new public class extending PopupToolbar that exposes an annotations property containing the currently selected annotations.
  • onPrepareTextSelectionPopupToolbar(TextSelectionPopupToolbar) — Called when the text selection popup toolbar is about to be displayed.
  • onPrepareLongPressPopupToolbar(PopupToolbar, int pageIndex, PointF pdfPoint)New, called when the long-press popup toolbar is about to be displayed. This toolbar appears when the user long-presses on an empty area of a document (outside of text selection or annotation selection). The pageIndex and pdfPoint parameters indicate where the long-press occurred in PDF coordinates.
  • onPrepareContentEditingPopupToolbar(PopupToolbar, int pageIndex, PointF pdfPoint)New, called when a content editing popup toolbar is about to be displayed. This toolbar appears when the user long-presses in content editing mode, either on a text block or on an empty area of the page. The pageIndex and pdfPoint parameters indicate where the long-press occurred in PDF coordinates.

Migration guide

This section covers breaking changes and how to update your code.

Annotation editing toolbar removal

The AnnotationEditingToolbar — the bar shown at the top or bottom of the screen when an annotation was selected — has been removed. Annotation editing actions (delete, edit, inspector, note, share, copy, play/record for sound) are now provided by a popup toolbar that appears next to the selected annotation on the page.

Removed classes

The following classes have been fully removed with no direct replacement. The popup toolbar is managed automatically by the SDK:

  • com.pspdfkit.ui.toolbar.AnnotationEditingToolbar
  • com.pspdfkit.ui.toolbar.grouping.presets.AnnotationEditingToolbarGroupingRule
  • com.pspdfkit.ui.toolbar.grouping.presets.AnnotationEditingToolbarItemPresets

What to remove from your code

  • AnnotationEditingToolbar instantiation — Remove entirely. The popup toolbar is managed automatically.
  • bindController()/unbindController() calls on AnnotationEditingToolbar — Remove these calls.
  • displayContextualToolbar()/removeContextualToolbar() calls for annotation editing — Remove these calls.
  • instanceof AnnotationEditingToolbar checks in onPrepareContextualToolbar — Remove these branches. The OnContextualToolbarLifecycleListener callbacks no longer fire for annotation editing.
  • Styling via pspdf__annotationEditingToolbarIconsStyle, pspdf__AnnotationEditingToolbarIcons, or PSPDFKit.AnnotationEditingToolbarIcons — No longer applies to annotation editing. If you were using these to customize note editor toolbar icons, see the styling migration section below.
  • Custom AnnotationEditingToolbarGroupingRule subclasses — No longer apply.

The popup toolbar provides actions based on the selected annotation type:

ActionConditions
CopyWhen copy is enabled for the selected annotations
DeleteWhen delete is enabled (not shown for Instant comment thread roots)
Inspector (color/style picker)Not shown for note or sound annotations or Instant comment thread roots
Note/CommentFor annotations that support notes (not for note annotations themselves)
EditFor note annotations (opens the note editor)
Play / RecordFor sound annotations
ShareFor annotation types with sharing enabled (free text, note, file, stamp with bitmap, sound)
Ungroup / GroupWhen selected annotations can be ungrouped or grouped

Styling migration

The removed AnnotationEditingToolbar style names don’t style the new annotation popup toolbar.

  • The annotation popup toolbar is styled via pspdf__popupToolbarStyle/PSPDFKit.PopupToolbar.
  • The popup toolbar uses text actions, not per-action themed icons, so there’s no direct replacement for old icon overrides like edit, share, copy, play, or record.
  • The note editor still has its own top app bar with undo/redo/delete actions. If you previously used the removed editing toolbar icon style names to customize those icons, rename them to the note editor toolbar names:
Old nameNew name
pspdf__annotationEditingToolbarIconsStylepspdf__noteEditorToolbarIconsStyle
pspdf__AnnotationEditingToolbarIconspspdf__NoteEditorToolbarIcons
PSPDFKit.AnnotationEditingToolbarIconsPSPDFKit.NoteEditorToolbarIcons

Controller and listener unification

Annotation creation and annotation editing were previously two separate modes with separate controllers and listeners. They have been unified into a single “annotating” mode.

Core concept change

BeforeAfter
Two separate modes: annotation creation and annotation editingOne unified mode: annotating
AnnotationCreationController for creationAnnotatingController for both
AnnotationEditingController for editingAnnotatingController for both
Separate listeners for each modeSingle OnAnnotatingModeChangeListener
Separate inspector controllersSingle AnnotatingInspectorController

Deleted interfaces

Deleted interfaceReplacement
AnnotationCreationControllerAnnotatingController
AnnotationEditingControllerAnnotatingController
OnAnnotationCreationModeChangeListenerOnAnnotatingModeChangeListener
OnAnnotationEditingModeChangeListenerOnAnnotatingModeChangeListener
OnAnnotationCreationModeSettingsChangeListenerOnAnnotatingModeSettingsChangeListener
AnnotationCreationInspectorControllerAnnotatingInspectorController
AnnotationEditingInspectorControllerAnnotatingInspectorController

Note that AnnotationCreationController was previously kept as a deprecated empty alias of AnnotatingController. That alias has now been removed, so code must migrate directly to AnnotatingController.

Deprecated (still available)

PdfFragment#enterAnnotationEditingMode() (both overloads) is deprecated. Use PdfFragment.setSelectedAnnotations() instead. There’s no need to enter annotating mode to edit annotations — the popup toolbar handles editing actions automatically.

PdfFragment#enterAnnotationCreationMode() (all overloads) is deprecated. Use enterAnnotatingMode(), enterAnnotatingMode(AnnotationTool), or enterAnnotatingMode(AnnotationTool, AnnotationToolVariant) instead.

Changed methods on PdfFragment

Removed methodReplacement
addOnAnnotationCreationModeChangeListener()addOnAnnotatingModeChangeListener()
removeOnAnnotationCreationModeChangeListener()removeOnAnnotatingModeChangeListener()
addOnAnnotationCreationModeSettingsChangeListener()addOnAnnotatingModeSettingsChangeListener()
removeOnAnnotationCreationModeSettingsChangeListener()removeOnAnnotatingModeSettingsChangeListener()
addOnAnnotationEditingModeChangeListener()addOnAnnotatingModeChangeListener()
removeOnAnnotationEditingModeChangeListener()removeOnAnnotatingModeChangeListener()

Changed methods on PdfUi/PdfActivityComponentsApi

Removed methodReplacement
setAnnotationEditingInspectorController()setEditingInspectorController()
setAnnotationCreationInspectorController()setCreationInspectorController()

Removed deprecated inner interfaces from AnnotationManager

These deprecated compatibility shim interfaces have been removed:

  • AnnotationManager.OnAnnotationCreationModeChangeListener
  • AnnotationManager.OnAnnotationCreationModeSettingsChangeListener
  • AnnotationManager.OnAnnotationEditingModeChangeListener

AnnotationManager.OnAnnotationSelectedListener still remains.

AnnotationCreationToolbar renamed to AnnotationToolbar

AnnotationCreationToolbar has been renamed to AnnotationToolbar. The toolbar’s generic type and listener interfaces have also changed,

Before:

class AnnotationCreationToolbar :
ContextualToolbar<AnnotationCreationController>,
OnAnnotationCreationModeSettingsChangeListener,
OnAnnotationCreationModeChangeListener { ... }

After:

class AnnotationToolbar :
ContextualToolbar<AnnotatingController>,
OnAnnotatingModeSettingsChangeListener,
OnAnnotatingModeChangeListener,
OnAnnotationSelectedListener { ... }

The nested type AnnotationCreationToolbar.ItemToAnnotationToolMapper is now AnnotationToolbar.ItemToAnnotationToolMapper.

The controller property type changed from AnnotationCreationController? to AnnotatingController?, and the bindController() parameter type changed from AnnotationCreationController to AnnotatingController.

Note that grouping rules (AnnotationCreationToolbarGroupingRule), item presets (AnnotationCreationToolbarItemPresets), item groups (AnnotationCreationToolbarItemGroups), and style attributes (pspdf__annotationCreationToolbarIconsStyle, pspdf__AnnotationCreationToolbarIcons, PSPDFKit.AnnotationCreationToolbarIcons) are unchanged.

Resource ID renames

All annotation toolbar XML resource IDs have been renamed to match the new class name:

Old ID prefixNew ID prefix
pspdf__annotation_creation_toolbar_*pspdf__annotation_toolbar_*

For example, R.id.pspdf__annotation_creation_toolbar is now R.id.pspdf__annotation_toolbar, R.id.pspdf__annotation_creation_toolbar_item_highlight is now R.id.pspdf__annotation_toolbar_item_highlight, and so on for all toolbar item and group IDs.

The old annotation editing toolbar IDs have been renamed to annotation popup toolbar IDs:

Old ID prefixNew ID prefix
pspdf__annotation_editing_toolbar_*pspdf__annotation_popup_toolbar_*

For example, R.id.pspdf__annotation_editing_toolbar_item_delete is now R.id.pspdf__annotation_popup_toolbar_item_delete.

OnPreparePopupToolbarListener is no longer a SAM interface

OnPreparePopupToolbarListener previously had a single abstract method (onPrepareTextSelectionPopupToolbar), making it usable as a lambda in Kotlin and Java. It now has four default methods (see popup toolbar customization above for the full list).

Because the interface is no longer a functional interface, lambda syntax no longer compiles. Update to use an explicit object expression (Kotlin) or anonymous class (Java).

Before (Kotlin):

pdfFragment.setOnPreparePopupToolbarListener { toolbar ->
toolbar.setOnPopupToolbarItemClickedListener { item ->
// Handle item click.
false
}
}

After (Kotlin):

pdfFragment.setOnPreparePopupToolbarListener(object : OnPreparePopupToolbarListener {
override fun onPrepareTextSelectionPopupToolbar(toolbar: TextSelectionPopupToolbar) {
toolbar.setOnPopupToolbarItemClickedListener { item ->
// Handle item click.
false
}
}
})

Behavioral change: Annotation deselection

When an annotation is deselected (without reselection) while in annotation mode, the SDK no longer exits the currently active mode. Previously, deselecting an annotation would call exitCurrentlyActiveMode(). Now, the annotating mode persists even when annotations are deselected, which allows continued annotation creation and editing.

Migration examples

The following examples show how to update common code patterns to use the new unified APIs.

Migrating annotation creation listener

Before:

fragment.addOnAnnotationCreationModeChangeListener(new OnAnnotationCreationModeChangeListener() {
@Override public void onEnterAnnotationCreationMode(AnnotationCreationController controller) {
// Handle enter.
}
@Override public void onChangeAnnotationCreationMode(AnnotationCreationController controller) {
// Handle change.
}
@Override public void onExitAnnotationCreationMode(AnnotationCreationController controller) {
// Handle exit.
}
});

After:

fragment.addOnAnnotatingModeChangeListener(new OnAnnotatingModeChangeListener() {
@Override public void onEnterAnnotatingMode(AnnotatingController controller) {
// Handle enter (covers both creation and editing).
}
@Override public void onChangeAnnotatingMode(AnnotatingController controller) {
// Handle change.
}
@Override public void onExitAnnotatingMode(AnnotatingController controller) {
// Handle exit.
}
});

Migrating annotation editing listener

Before:

fragment.addOnAnnotationEditingModeChangeListener(new OnAnnotationEditingModeChangeListener() {
@Override public void onEnterAnnotationEditingMode(AnnotationEditingController controller) {
annotationEditingToolbar.bindController(controller);
toolbarCoordinatorLayout.displayContextualToolbar(annotationEditingToolbar, true);
}
@Override public void onChangeAnnotationEditingMode(AnnotationEditingController controller) { }
@Override public void onExitAnnotationEditingMode(AnnotationEditingController controller) {
toolbarCoordinatorLayout.removeContextualToolbar(true);
annotationEditingToolbar.unbindController();
}
});

After: Editing is handled automatically by the popup toolbar. The toolbar management code is no longer needed. If you need to react to mode changes, use OnAnnotatingModeChangeListener (see above).

Migrating inspector controller setup

Before:

activity.setAnnotationCreationInspectorController(myCreationInspectorController);
activity.setAnnotationEditingInspectorController(myEditingInspectorController);

After:

activity.setCreationInspectorController(myAnnotatingInspectorController);
activity.setEditingInspectorController(myAnnotatingInspectorController);

Migrating custom inspector controllers

Before:

class MyInspector implements AnnotationCreationInspectorController {
void bindAnnotationCreationController(AnnotationCreationController controller) { ... }
void unbindAnnotationCreationController() { ... }
}

After:

class MyInspector implements AnnotatingInspectorController {
void bindController(AnnotatingController controller) { ... }
void unbindController() { ... }
}

Migrating AnnotationToolbar binding

Before:

AnnotationCreationToolbar annotationToolbar = ...;
AnnotationCreationController controller = ...;
annotationToolbar.bindController(controller);

After:

AnnotationToolbar annotationToolbar = ...;
AnnotatingController controller = ...;
annotationToolbar.bindController(controller);

FreeTextAnnotationUtils changes

FreeTextAnnotationUtils has been converted from a Java utility class to Kotlin top-level extension functions. The ScaleMode enum and the placeCallOutPoints method have moved, and a new resizeToFitText extension function has been added.

ScaleMode moved to top-level enum

ScaleMode is no longer a nested enum inside FreeTextAnnotationUtils. It’s now a top-level enum in the com.pspdfkit.utils package.

BeforeAfter
com.pspdfkit.utils.FreeTextAnnotationUtils.ScaleModecom.pspdfkit.utils.ScaleMode

Before:

import com.pspdfkit.utils.FreeTextAnnotationUtils.ScaleMode
val mode = ScaleMode.SCALE

After:

import com.pspdfkit.utils.ScaleMode
val mode = ScaleMode.SCALE

placeCallOutPoints is now an extension function

FreeTextAnnotationUtils.placeCallOutPoints(annotation) is now an extension function on FreeTextAnnotation.

Before:

import com.pspdfkit.utils.FreeTextAnnotationUtils
FreeTextAnnotationUtils.placeCallOutPoints(freeTextAnnotation)

After:

import com.pspdfkit.utils.placeCallOutPoints
freeTextAnnotation.placeCallOutPoints()

New resizeToFitText extension function

FreeTextAnnotation.resizeToFitText() was mistakenly removed in v10.8 and has been readded in this release as a Kotlin extension function on FreeTextAnnotation. It resizes the annotation bounding box so the text fits inside its bounds, using the specified ScaleMode for width and height independently:

import com.pspdfkit.utils.ScaleMode
import com.pspdfkit.utils.resizeToFitText
// Resize to exactly fit the text content.
freeTextAnnotation.resizeToFitText(document, ScaleMode.SCALE, ScaleMode.SCALE)
// Only expand, never shrink.
freeTextAnnotation.resizeToFitText(document, ScaleMode.EXPAND, ScaleMode.EXPAND)
// Keep width fixed, scale height to fit.
freeTextAnnotation.resizeToFitText(document, ScaleMode.FIXED, ScaleMode.SCALE)