Nutrient Android SDK 11.3 release notes
RSS26 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.
TextSelectionToolbarand theisTextSelectionPopupToolbarEnabledconfiguration 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
DocumentViewposition 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
restoreLastViewedPageoption 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. SeeFreeTextAnnotationUtilschanges for details. - Fixed a crash caused by
ClosedByInterruptExceptionduring 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.
Popup toolbar customization
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.AnnotationPopupToolbaris a new public class extendingPopupToolbarthat exposes anannotationsproperty 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). ThepageIndexandpdfPointparameters 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. ThepageIndexandpdfPointparameters 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.AnnotationEditingToolbarcom.pspdfkit.ui.toolbar.grouping.presets.AnnotationEditingToolbarGroupingRulecom.pspdfkit.ui.toolbar.grouping.presets.AnnotationEditingToolbarItemPresets
What to remove from your code
AnnotationEditingToolbarinstantiation — Remove entirely. The popup toolbar is managed automatically.bindController()/unbindController()calls onAnnotationEditingToolbar— Remove these calls.displayContextualToolbar()/removeContextualToolbar()calls for annotation editing — Remove these calls.instanceof AnnotationEditingToolbarchecks inonPrepareContextualToolbar— Remove these branches. TheOnContextualToolbarLifecycleListenercallbacks no longer fire for annotation editing.- Styling via
pspdf__annotationEditingToolbarIconsStyle,pspdf__AnnotationEditingToolbarIcons, orPSPDFKit.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
AnnotationEditingToolbarGroupingRulesubclasses — No longer apply.
Popup toolbar actions
The popup toolbar provides actions based on the selected annotation type:
| Action | Conditions |
|---|---|
| Copy | When copy is enabled for the selected annotations |
| Delete | When 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/Comment | For annotations that support notes (not for note annotations themselves) |
| Edit | For note annotations (opens the note editor) |
| Play / Record | For sound annotations |
| Share | For annotation types with sharing enabled (free text, note, file, stamp with bitmap, sound) |
| Ungroup / Group | When 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 name | New name |
|---|---|
pspdf__annotationEditingToolbarIconsStyle | pspdf__noteEditorToolbarIconsStyle |
pspdf__AnnotationEditingToolbarIcons | pspdf__NoteEditorToolbarIcons |
PSPDFKit.AnnotationEditingToolbarIcons | PSPDFKit.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
| Before | After |
|---|---|
| Two separate modes: annotation creation and annotation editing | One unified mode: annotating |
AnnotationCreationController for creation | AnnotatingController for both |
AnnotationEditingController for editing | AnnotatingController for both |
| Separate listeners for each mode | Single OnAnnotatingModeChangeListener |
| Separate inspector controllers | Single AnnotatingInspectorController |
Deleted interfaces
| Deleted interface | Replacement |
|---|---|
AnnotationCreationController | AnnotatingController |
AnnotationEditingController | AnnotatingController |
OnAnnotationCreationModeChangeListener | OnAnnotatingModeChangeListener |
OnAnnotationEditingModeChangeListener | OnAnnotatingModeChangeListener |
OnAnnotationCreationModeSettingsChangeListener | OnAnnotatingModeSettingsChangeListener |
AnnotationCreationInspectorController | AnnotatingInspectorController |
AnnotationEditingInspectorController | AnnotatingInspectorController |
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 method | Replacement |
|---|---|
addOnAnnotationCreationModeChangeListener() | addOnAnnotatingModeChangeListener() |
removeOnAnnotationCreationModeChangeListener() | removeOnAnnotatingModeChangeListener() |
addOnAnnotationCreationModeSettingsChangeListener() | addOnAnnotatingModeSettingsChangeListener() |
removeOnAnnotationCreationModeSettingsChangeListener() | removeOnAnnotatingModeSettingsChangeListener() |
addOnAnnotationEditingModeChangeListener() | addOnAnnotatingModeChangeListener() |
removeOnAnnotationEditingModeChangeListener() | removeOnAnnotatingModeChangeListener() |
Changed methods on PdfUi/PdfActivityComponentsApi
| Removed method | Replacement |
|---|---|
setAnnotationEditingInspectorController() | setEditingInspectorController() |
setAnnotationCreationInspectorController() | setCreationInspectorController() |
Removed deprecated inner interfaces from AnnotationManager
These deprecated compatibility shim interfaces have been removed:
AnnotationManager.OnAnnotationCreationModeChangeListenerAnnotationManager.OnAnnotationCreationModeSettingsChangeListenerAnnotationManager.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 prefix | New 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 prefix | New 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.
| Before | After |
|---|---|
com.pspdfkit.utils.FreeTextAnnotationUtils.ScaleMode | com.pspdfkit.utils.ScaleMode |
Before:
import com.pspdfkit.utils.FreeTextAnnotationUtils.ScaleMode
val mode = ScaleMode.SCALEAfter:
import com.pspdfkit.utils.ScaleMode
val mode = ScaleMode.SCALEplaceCallOutPoints 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.ScaleModeimport 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)