---
title: "Nutrient Android SDK 12.0 release notes"
canonical_url: "https://www.nutrient.io/guides/android/releases/12-0/"
md_url: "https://www.nutrient.io/guides/android/releases/12-0.md"
last_updated: "2026-09-29T00:00:00.000Z"
description: "Nutrient Android SDK 12.0 release notes: Jetpack Compose toolbars, Material 3 sheets, a unified color picker, a redesigned page grid, and a sepia theme."
---

29 September 2026

Nutrient Android SDK 12.0 is a major release that moves the viewer’s user interface from Android Views to Jetpack Compose and Material 3. Compose now renders the main toolbar; the annotation, document editing, and content editing toolbars; and the inline search bar. It also renders the document overview grid; the outline, document info, settings, and share surfaces; and the annotation inspector’s color picker. Toolbar content is now defined through a single Compose-based item model instead of the Android options-menu contract. The SDK also gains Material 3 Expressive floating toolbars for hosts that draw their own chrome.

Because the View-based toolbar classes are removed rather than deprecated, this release contains source-breaking API changes. Refer to the [migration guide](https://www.nutrient.io/guides/android/migration-guides/12-migration-guide.md) for a complete list of removed and replaced APIs, before and after code, and the behavior changes to check.

This release contains many additional fixes and enhancements. For the full list of changes, refer to our [changelog](https://www.nutrient.io/guides/android/changelog.md#12.0.0).

## Jetpack Compose toolbars

The main toolbar of `PdfActivity` and `PdfUiFragment` is a Jetpack Compose implementation. One source of truth defines toolbar actions. Supply items with a `ToolbarItemsProvider` and handle taps with an `OnToolbarItemClickListener`, on `PdfActivity`, `PdfUiFragment`, and the Compose `DocumentState` alike. Menu XML, `onCreateOptionsMenu`, `onPrepareOptionsMenu`, and `OnMenuItemsGenerateListener` no longer drive the toolbar.

The annotation creation, document editing, and content editing toolbars are Compose toolbars too. A `ToolbarCoordinator` drives them and exposes their items, grouping, docking position, and actions. `ToolbarCoordinatorLayout` and the View `ContextualToolbar` hierarchy are removed. Custom activity layouts host the toolbars through a single `ComposeView`, and custom `PdfFragment` hosts mount them with `nutrientToolbarsComposeView`. The legacy docked `TextSelectionToolbar` is removed as well, leaving the popup toolbar as the only text selection toolbar.

The inline search bar is rendered inside the main toolbar’s own composition and survives rotation. Observe search activity with `PdfUi.isInlineSearchActive()`, or through the coordinator’s `searchSession` flow in a Compose host.

For hosts that draw their own chrome, `NutrientMainToolbar` and `NutrientContextualToolbar` have the shape of Material 3’s `TopAppBar`. They take `navigationIcon`, `title`, `actions`, and `searchBar` slots (or one `content` lambda), plus flat `shape`, `shadowElevation`, `windowInsets`, and `colors` parameters. Their defaults live in `NutrientMainToolbarDefaults` and `NutrientContextualToolbarDefaults`, and a shared `ToolbarItemIndication` covers every item’s pressed and selected states. The SDK’s own pieces (the title, the item row, and the search bar) are public composables, so a custom layout keeps the coordinator’s items. Set a navigation icon with `setToolbarNavigationIcon` and `setOnToolbarNavigationClickListener` on `PdfActivity`, `PdfUiFragment`, and `DocumentState`. `ToolbarCoordinator.setMainToolbarHostVisible` hides the main toolbar without the SDK undoing it, and `setContextualToolbarAllowedPositions` restricts the docks a contextual toolbar can be dragged to.

Long-pressing an icon-only toolbar button shows a tooltip naming the action. In landscape, the main toolbar stays clear of the navigation bar. The system bars stay visible while a contextual toolbar is onscreen, and the document no longer shifts when the toolbar appears or changes dock. The annotation toolbar’s undo/redo button undoes or redoes in one tap when only one is possible, and opens its submenu only when both are.

### Floating toolbars

`NutrientFloatingToolbar` and `NutrientFloatingContextualToolbar` are Material 3 Expressive floating pills. The `ToolbarCoordinator` drives them, and users can drag and dock them to any window edge. They lay out horizontally or vertically with spring-based animations and optionally collapse to their active item. `NutrientFloatingToolbarItemButton`, `NutrientFloatingToolbarMenuItem`, and `NutrientFloatingToolbarSearchTheme` enable a host to lay out its own pills from the same building blocks. `NutrientDocumentStatusBarScrim` blurs and tints the status bar strip a floating pill leaves uncovered. The Catalog app consolidates its toolbar examples around these hosting entries and renames them after the surface they customize. The Catalog’s Compose PDF Viewer example replaces the standalone `simple-compose` example app. It’s a complete Compose viewer with a host-rendered main toolbar over `DocumentView`.

## Document tab bar

The document tab bar is a Jetpack Compose implementation. `PdfTabBar` keeps its API for Java callers, but it’s now a Kotlin class. Kotlin subclasses override properties such as `tabs` instead of getters; see [the migration guide](https://www.nutrient.io/guides/android/migration-guides/12-migration-guide.md#pdffragment-and-pdftabbar-are-kotlin-classes). The same UI is public as `NutrientTabBar`. Bind it to a `DocumentCoordinator` through the new `DocumentState.documentCoordinator`, or drive it from your own list of tabs. It takes `TabBarColors`, `NutrientTabBarDefaults.dimensions()`, a tab shape and spacing, and a slot for custom tab content.

## Material 3 modal surfaces

The outline container, the document info screen, the settings dialog, and the share menu present as Material 3 modal sheets with drag-to-dismiss. On expanded windows, 840dp wide and up, the outline and the settings present as a side sheet anchored to the trailing edge. The SDK clamps both sheets to the same width the rest of the UI uses. The new `pspdf__maxWidth` and `pspdf__sheetPresentationMode` theme attributes make this configurable.

The settings sheet is simpler. The preset buttons and the keep-screen-on switch are gone, and color circles now pick the page appearance. The snapping switches moved to the annotation inspector. Scroll direction, page transition, and page layout changes apply to the open document without restarting the activity. In the dark theme, the settings and sharing sheets derive their Material 3 colors from the theme. The icon-only settings options carry accessibility labels. The new `NutrientSettingsView` composable renders the SDK’s settings rows wherever you place them. Its slots replace or decorate an individual row; see [customizing the settings UI](https://www.nutrient.io/guides/android/user-interface/custom-settings-ui.md).

## Sepia page appearance

Alongside Default and Night, pages can render in a sepia appearance matching the iOS SDK. It uses cream paper and dark brown text, and annotations drawn as overlays keep their colors. Users pick it from the Theme row of the settings sheet, and integrators enable it with `sepia()` on `PdfConfiguration.Builder`, `PdfActivityConfiguration.Builder`, or `PageRenderConfiguration.Builder`, or through `SettingsOptions.sepia`.

## Unified color picker

The annotation inspector’s two color pickers are one Compose-based picker. The palette and the custom color entry are tabs of a single view, and picking a custom color no longer loses the palette selection. `setRestrictToAvailableColors()` replaces `setCustomColorPickerEnabled()`. It now hides the recently used colors and color variations as well as the custom entry, so a configured palette is enforced.

## Redesigned document overview

The document overview’s page grid is a Jetpack Compose implementation with Material 3 styling, keeping the `PdfThumbnailGrid` API and its theme attributes. In `PdfActivity`, the current page shrinks into its thumbnail when the grid opens and grows back out when the user taps a page. The grid extends edge to edge under the system bars. Reordering pages by drag creates a single undo step.

The document editing entry point moved from a floating action button into the toolbars, matching iOS. While the grid is displayed, the main toolbar shows a document editor item. The document editing toolbar gains an Add Page item backed by the new `PdfThumbnailGrid.createNewPage()`. The SDK caches thumbnails on disk and renders them starting from the visible page.

## Saving and sharing

The sharing menu offers Save As… alongside Open, so a writable document can be written as a renamed, page-filtered, or flattened copy. `PdfUi.showSaveAsDialog()` opens the Save As dialog programmatically. Leaving the document editor with unsaved page edits now offers Save, Discard Changes, and Cancel, matching the content editor and the iOS SDK.

Opening a local file the app lacks storage permission for surfaces a dedicated `FileAccessPermissionException`. On Android 11 and later, the SDK also prompts the user to grant All files access and reloads the document once granted. A new public helper checks external storage permission correctly under scoped storage.

## Rendering and platform

`PdfConfiguration` and `PageRenderConfiguration` gain overprint preview and black rendering options, with overprint preview defaulting to automatic simulation. Rendering fidelity improved for documents that combine content in the cyan, magenta, yellow, key (CMYK) color model with spot colors, soft masks, and transparency groups. Ink, shape, and stamp annotations render at full resolution on displays larger than 2048px.

The SDK targets and compiles against API 37. It upgrades its third-party dependencies, notably Kotlin 2.4.10, Jetpack Compose 1.12.0, AndroidX Lifecycle 2.11.0, Fragment 1.9.0, and AppCompat 1.8.0.

## Instant

Instant Comments can be edited when the layer’s collaboration permissions grant `comments:edit`. `InstantAnnotationProvider.NonAnnotationChange` gains a `COMMENT_UPDATED` case, and `InstantDocumentDescriptor.hasStaleBackingPdf()` reports that a downloaded document’s pages changed on the server.

## Bug fixes

This release addresses many issues across the user interface and the model layer. Core fixes include several for redaction, form field JavaScript, and CMYK rendering. A crash fix covers `DocumentView` and `InstantDocumentView` when first composed below the `STARTED` lifecycle state, such as inside a Compose `NavHost`. For the full list, refer to the [changelog](https://www.nutrient.io/guides/android/changelog.md#12.0.0).

## Migration guide {#migration-guide}

Version 12.0 removes the View-based toolbar classes, the options-menu toolbar contract, `ToolbarCoordinatorLayout`, the legacy `TextSelectionToolbar`, `CustomColorPickerInspectorDetailView`, and `setCustomColorPickerEnabled()`. It replaces the document overview grid’s `RecyclerView` and floating action button, makes `PdfDocument.getPageLabel()` nullable, and adds a `COMMENT_UPDATED` case to `InstantAnnotationProvider.NonAnnotationChange`. It also converts `PdfFragment` and `PdfTabBar` to Kotlin, and changes how the outline, settings, and share surfaces are presented and themed. It retires the standalone `simple-compose` example in favor of the Catalog’s Compose PDF Viewer. The [Nutrient 12 migration guide](https://www.nutrient.io/guides/android/migration-guides/12-migration-guide.md) walks through each area with before and after code.
---

## Related pages

- [10 10 1](/guides/android/releases/10-10-1.md)
- [10 10](/guides/android/releases/10-10.md)
- [10 6](/guides/android/releases/10-6.md)
- [10 7](/guides/android/releases/10-7.md)
- [10 8](/guides/android/releases/10-8.md)
- [10 9](/guides/android/releases/10-9.md)
- [11 0](/guides/android/releases/11-0.md)
- [11 1](/guides/android/releases/11-1.md)
- [11 2](/guides/android/releases/11-2.md)
- [11 3 1](/guides/android/releases/11-3-1.md)
- [11 3](/guides/android/releases/11-3.md)
- [11 4](/guides/android/releases/11-4.md)
- [11 5](/guides/android/releases/11-5.md)
- [11 6](/guides/android/releases/11-6.md)
- [11 7](/guides/android/releases/11-7.md)

