---
title: "Hosting the Nutrient toolbars in Jetpack Compose | Nutrient Android SDK"
canonical_url: "https://www.nutrient.io/guides/android/jetpack-compose/components/toolbar-hosting/"
md_url: "https://www.nutrient.io/guides/android/jetpack-compose/components/toolbar-hosting.md"
last_updated: "2026-09-29T00:00:00.000Z"
description: "How the Nutrient toolbars are wired: the ToolbarCoordinator, how to get it in every host, NutrientToolbars and NutrientToolbarScaffold for placing the toolbars with the SDK’s docking chrome, nutrientToolbarsComposeView for View layouts, and the inset model."
---

# Toolbar hosting

Every Nutrient toolbar, including the SDK’s own and any that a host composes, renders from one shared object: the [`ToolbarCoordinator`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.compose.toolbar.adapter/-toolbar-coordinator/index.html). The SDK writes the items, document title, UI visibility, shown contextual toolbar, and search session into the coordinator. It also reads the actions that the toolbars emit. This page explains the coordinator and how to get it in each kind of host. It also covers the composables that place the toolbars with the SDK’s docking behavior, so a host doesn’t have to rebuild that behavior.

## The coordinator

`ToolbarCoordinator` is state held in a `ViewModel`. The `ViewModel` is scoped to the host that requested the coordinator, which is either an activity or a fragment. Because of that scoping, the coordinator survives configuration changes and outlives the view of `PdfUiFragment`. It has these main surfaces:

| Surface                                                                                | What it holds                                                                                                |
| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `frame: StateFlow<ToolbarFrame>`                                                       | The main toolbar’s `isVisible`, `title`, `height`, `insets`, and `navigationIcon`.                           |
| `items: StateFlow<ToolbarItems>`                                                       | The main toolbar’s `visible` and `overflow` items, after the host’s `ToolbarItemsProvider` ran.              |
| `contextualToolbar: StateFlow<ContextualToolbarState?>`                                | The shown contextual bar, or `null`: its `kind`, `items`, `position`, `isDraggable`, and `allowedPositions`. |
| `searchSession: StateFlow<ToolbarSearchSession?>`                                      | Inline search: `isActive`, `state` (query, results), and `actions`.                                          |
| `addActionListener`, `addActionInterceptor`, `dispatch`                                | The action bus every toolbar dispatches into and the SDK handles from.                                       |
| `setMainToolbarHostVisible`, `setMainToolbarInsets`, `setContextualToolbarPosition`, … | Host controls over what the SDK renders.                                                                     |

Every `add…` method returns a `ToolbarSubscription`. Close the subscription when the host goes away.

### Getting it

| Host                                     | How                                                                                          |
| ---------------------------------------- | -------------------------------------------------------------------------------------------- |
| `PdfActivity` or any `ComponentActivity` | `nutrientToolbarCoordinator()` from `com.pspdfkit.jetpack.compose.toolbar`                   |
| `PdfUiFragment` or any `Fragment`        | `nutrientToolbarCoordinator()` on the fragment, which returns the fragment’s own coordinator |
| Compose `DocumentView`                   | `documentState.toolbarCoordinator.collectAsState()`, `null` until the document UI is ready   |
| A Compose host without an SDK UI         | `rememberNutrientToolbarCoordinator()`, a coordinator scoped to the composition              |

## Choosing a hosting shape

| You have                                   | Use                                                                                                                                                                                                        |
| ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `PdfActivity` with the default layout      | Nothing to host. Customize items with the [main toolbar](https://www.nutrient.io/guides/android/customizing-the-interface/customizing-menus.md) and [contextual toolbars](https://www.nutrient.io/guides/android/customizing-the-interface/customizing-the-toolbar.md) guides.                                                                              |
| `PdfActivity` with a custom layout         | A `ComposeView` with the ID `pspdf__toolbar_compose_host` overlaying the content; the SDK mounts into it. See [extending PdfActivity](https://www.nutrient.io/guides/android/customizing-the-interface/extending-pdfactivity.md).                                                                   |
| `PdfActivity`, but your own toolbar look   | `defaultToolbarEnabled(false)` and/or `defaultContextualToolbarEnabled(false)`. Then compose `NutrientMainToolbar` or a floating pill over the activity’s coordinator. `CustomToolbarsPdfActivityExample`. |
| A bare `PdfFragment` in a Compose activity | `NutrientToolbars` around the fragment container, plus the binders. `CustomToolbarsPdfFragmentExample`. See [usage within fragment](https://www.nutrient.io/guides/android/customizing-the-interface/using-toolbars-within-fragment.md).                                                                     |
| A bare `PdfFragment` in a View layout      | `nutrientToolbarsComposeView(context, coordinator)` added over the fragment container. `CustomToolbarsPdfFragmentViewExample`.                                                                             |
| Compose `DocumentView`                     | `defaultToolbarEnabled(false)` and compose the bars from `documentState.toolbarCoordinator`. `CustomToolbarsDocumentViewExample`.                                                                          |

## NutrientToolbars

`NutrientToolbars` is the SDK’s toolbar stack as a composable. It places the main toolbar in the top slot and the contextual toolbar in its top, start, or end dock. It also draws the drop-zone chrome while the user drags a bar. When a vertical bar doesn’t fit, fit correction moves the bar from a side dock to the top. `NutrientToolbars` also saves the dock the user chose, under the same preference keys that `PdfActivity` uses. Wrap the content in it:

```kotlin

NutrientToolbars(
    coordinator = coordinator,
    showMainToolbar = true,
    topWindowInset = topInset,       // the insets your layout has not consumed.
    bottomWindowInset = bottomInset,
    modifier = Modifier.fillMaxSize(),
) {
    // Content reads the inset so it clears a top-docked bar.
    MyDocument(Modifier.fillMaxSize().padding(top = LocalToolbarContentInset.current))
}

```

`LocalToolbarContentInset` is the height that the content should leave free at the top. The value is zero while no bar is docked there, so the document doesn’t move when a side-docked bar appears.

```kotlin

@Composable
fun NutrientToolbars(
    coordinator: ToolbarCoordinator,
    modifier: Modifier = Modifier,
    showMainToolbar: Boolean = true,
    showContextualToolbar: Boolean = true,
    defaultGroupingProvider: ContextualToolbarGroupingProvider? = null,
    dragListener: NutrientContextualToolbarDragListener? = null,
    onEffectivePositionChanged: ((ToolbarPosition?) -> Unit)? = null,
    topWindowInset: Dp = 0.dp,
    bottomWindowInset: Dp = 0.dp,
    leftWindowInset: Dp = 0.dp,
    rightWindowInset: Dp = 0.dp,
    content: @Composable () -> Unit,
)

```

With `showMainToolbar = false`, the composable keeps only the contextual bars. This is the common setup for a host with its own app bar. `onEffectivePositionChanged` reports the dock where the contextual bar is actually laid out, after fit correction.

## NutrientToolbarScaffold

`NutrientToolbarScaffold` is the layer under `NutrientToolbars`. It provides the same placement, docking, and drag chrome, with slots for the content of each toolbar position. Use it to put custom composables into the SDK’s dock slots:

```kotlin

NutrientToolbarScaffold(
    coordinator = coordinator,
    mainToolbar = { NutrientMainToolbar(coordinator, Modifier.fillMaxWidth(), shape = RoundedCornerShape(bottomStart = 16.dp, bottomEnd = 16.dp)) },
    contextualToolbar = {
        // ContextualToolbarSlotScope: the dock the scaffold resolved, and the drag listener that moves the bar between docks.
        NutrientContextualToolbar(coordinator, effectivePosition = effectivePosition, dragListener = dragListener)
    },
) {
    // Required: the content the toolbars are placed over, usually the document.
    DocumentView(documentState = documentState, modifier = Modifier.fillMaxSize())
}

```

The trailing `content` lambda is required and holds the content that the toolbars are placed over. The other parameters configure the docks. `contextualToolbarSize`, `verticalMargin`, `horizontalMargin`, `dragTargetColor`, and an outer `dragListener` default to the themed values in `NutrientContextualToolbarDefaults`. The four window insets default to `0.dp`.

## nutrientToolbarsComposeView

For a View layout, `nutrientToolbarsComposeView(context, coordinator, showMainToolbar, defaultGroupingProvider)` returns a `ComposeView` containing `NutrientToolbars`. Add the view over the document with `match_parent` in both dimensions. While no toolbar is shown, the view paints nothing and passes touches through. Its docking logic follows the view’s window-attach lifecycle. The `pspdf__toolbar_compose_host` slot in the SDK’s own activity layout plays the same role.

## Insets

Three layers decide what the main toolbar keeps clear of:

1. **The coordinator’s frame.** `ToolbarFrame.insets` is a `ToolbarInsets`. `StatusBars` is the default, and it’s correct for an edge-to-edge mount at the top of the window. `None` means the host already spaces the bar, and `Custom(top, bottom, start, end)` takes the four insets. Set the insets with `coordinator.setMainToolbarInsets(...)`. This setting controls the SDK-mounted toolbar in `PdfActivity` and `PdfUiFragment`. It’s useful when an embedded fragment sits below other chrome.

2. **`NutrientMainToolbarDefaults.windowInsets(coordinator)`**, the composable’s default `windowInsets` parameter. It uses the frame’s insets, plus the side system bars and the display cutout in landscape. This keeps the trailing overflow item from rendering under the navigation buttons.

3. **The `windowInsets` parameter** on `NutrientMainToolbar` replaces both when a host passes it.

`NutrientToolbars` and `NutrientToolbarScaffold` take the insets as `Dp` values because they position several bars. Pass the insets that the host layout hasn’t consumed.

## Main toolbar visibility

The SDK toggles `coordinator.frame.isVisible` whenever the user interface shows or hides. To hide the main toolbar and keep it hidden through those toggles, use the host veto:

```kotlin

coordinator.setMainToolbarHostVisible(false) // the SDK's own show/hide cannot undo this.
coordinator.setMainToolbarHostVisible(true)  // back to whatever the SDK last requested.

```

## Related

- [Main toolbar](https://www.nutrient.io/guides/android/jetpack-compose/components/main-toolbar.md), [contextual toolbar](https://www.nutrient.io/guides/android/jetpack-compose/components/contextual-toolbar.md), [floating toolbars](https://www.nutrient.io/guides/android/jetpack-compose/components/floating-toolbars.md), and [tab bar](https://www.nutrient.io/guides/android/jetpack-compose/components/tab-bar.md) — The composables you place with these hosts.

- [Usage within fragment](https://www.nutrient.io/guides/android/customizing-the-interface/using-toolbars-within-fragment.md) — The binders that connect a bare `PdfFragment`’s modes to the coordinator.

- Catalog app — `CustomToolbarsPdfActivityExample`, `CustomToolbarsPdfFragmentExample`, `CustomToolbarsPdfFragmentViewExample`, `CustomToolbarsDocumentViewExample`, and `DocumentPagerExample`.
---

## Related pages

- [Contextual toolbar](/guides/android/jetpack-compose/components/contextual-toolbar.md)
- [Floating toolbars](/guides/android/jetpack-compose/components/floating-toolbars.md)
- [Main toolbar](/guides/android/jetpack-compose/components/main-toolbar.md)
- [Tab bar](/guides/android/jetpack-compose/components/tab-bar.md)

