---
title: "Tabbed Documents (Compose)"
canonical_url: "https://www.nutrient.io/guides/android/samples/tabbed-documents-compose-kotlin/"
md_url: "https://www.nutrient.io/guides/android/samples/tabbed-documents-compose-kotlin.md"
last_updated: "2026-11-02T14:08:15.330Z"
description: "Render a floating-pill main toolbar with a rounded, spaced NutrientTabBar below it above a DocumentView, and open more documents into it."
---

# Tabbed Documents (Compose)

Render a floating-pill main toolbar with a rounded, spaced NutrientTabBar below it above a DocumentView, and open more documents into it.

[Get Started](https://www.nutrient.io/sdk/android/getting-started.md)

[All Samples](https://www.nutrient.io/guides/android/samples.md)

[Download](https://www.nutrient.io/guides/android/downloads.md)

[Launch Demo](https://www.nutrient.io/demo/)

---

```kotlin

/*
 *   Copyright © 2026 PSPDFKit GmbH. All rights reserved.
 *
 *   The Nutrient sample applications are licensed with a modified BSD license.
 *   Please see License for details. This notice may not be removed from this file.
 */

package com.pspdfkit.catalog.examples.kotlin

import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.activity.compose.BackHandler
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SmallFloatingActionButton
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.pspdfkit.catalog.R
import com.pspdfkit.catalog.SdkExample
import com.pspdfkit.catalog.tasks.ExtractAssetTask
import com.pspdfkit.catalog.ui.theming.CatalogTheme
import com.pspdfkit.catalog.ui.theming.enableConfigurationEdgeToEdge
import com.pspdfkit.catalog.ui.theming.isNightTheme
import com.pspdfkit.compose.tabs.composables.NutrientTabBar
import com.pspdfkit.compose.tabs.composables.NutrientTabBarDefaults
import com.pspdfkit.compose.theme.MainToolbarColors
import com.pspdfkit.compose.theme.NutrientTheme
import com.pspdfkit.compose.theme.ToolbarPopupColors
import com.pspdfkit.compose.theme.UiColorScheme
import com.pspdfkit.compose.theme.getUiColors
import com.pspdfkit.compose.toolbar.composables.NutrientMainToolbar
import com.pspdfkit.configuration.activity.PdfActivityConfiguration
import com.pspdfkit.configuration.activity.TabBarHidingMode
import com.pspdfkit.jetpack.compose.interactors.rememberDocumentState
import com.pspdfkit.jetpack.compose.views.DocumentView
import com.pspdfkit.ui.DocumentCoordinator
import com.pspdfkit.ui.DocumentDescriptor
import com.pspdfkit.ui.tabs.PdfTabBarCloseMode
import com.pspdfkit.utils.getSupportParcelableExtra
import io.nutrient.ui.theme.getTabBarColors

/**
 * Shows several documents in one [DocumentView] under app-owned chrome that floats over the document: a
 * [NutrientMainToolbar] rendered as a pill, and below it a [NutrientTabBar] with rounded, spaced tabs in the app's
 * Material colors plus an add button that opens another document in a new tab. Because the chrome overlays the
 * document rather than sitting above it, hiding it in immersive mode leaves the page where it is.
 *
 * Both bars bind to coordinators the [com.pspdfkit.jetpack.compose.interactors.DocumentState] publishes once the
 * document UI is ready: the toolbar coordinator and the [DocumentCoordinator]. The SDK's own main toolbar and tab
 * bar are disabled through the configuration.
 */
class DocumentTabsComposeExample(context: Context) :
    SdkExample(context, R.string.documentTabsComposeExampleTitle, R.string.documentTabsComposeExampleDescription) {
    override fun launchExample(context: Context, configuration: PdfActivityConfiguration.Builder) {
        ExtractAssetTask.extract(WELCOME_DOC, title, context) { documentFile ->
            val intent = Intent(context, DocumentTabsComposeActivity::class.java)
            intent.putExtra(DocumentTabsComposeActivity.EXTRA_URI, Uri.fromFile(documentFile))
            context.startActivity(intent)
        }
    }
}

class DocumentTabsComposeActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val uri = intent.getSupportParcelableExtra(EXTRA_URI, Uri::class.java)!!
        val configuration = PdfActivityConfiguration.Builder(this)
            // The activity renders its own main toolbar and tab bar above the document, so the SDK's stay hidden..defaultToolbarEnabled(false).setTabBarHidingMode(TabBarHidingMode.HIDE)
            // Keep the pill to a single row: no document title overlay strip below the toolbar items..documentTitleOverlayEnabled(false).build()

        enableConfigurationEdgeToEdge(configuration)
        setContent {
            CatalogTheme(darkTheme = configuration.isNightTheme) {
                TabbedDocuments(uri, configuration)
            }
        }
    }

    companion object {
        const val EXTRA_URI = "DocumentTabsComposeActivity.DocumentUri"
    }
}

@Composable
private fun TabbedDocuments(uri: Uri, configuration: PdfActivityConfiguration) {
    val context = LocalContext.current
    val documentState = rememberDocumentState(uri, configuration)

    // The DocumentView publishes both coordinators once its UI is ready. They are null until then, so the bars are
    // rendered only once they are non-null.
    val toolbarCoordinator by documentState.toolbarCoordinator.collectAsState()
    val documentCoordinator by documentState.documentCoordinator.collectAsState()

    // Let the SDK handle back the layered way: close an overlay view (outline, page grid,...) first.
    val overlayViewShown by documentState.viewWithOverlappingToolbarShown.collectAsState()
    val imeVisible = WindowInsets.ime.getBottom(LocalDensity.current) > 0
    BackHandler(enabled = overlayViewShown &&!imeVisible) {
        documentState.handleBackPress()
    }

    // Cycles through the extra documents the add button opens.
    var nextDocument by rememberSaveable { mutableIntStateOf(0) }

    // The toolbar frame's visibility flips with immersive mode (tap-to-hide chrome). The SDK's own toolbar animates
    // on it; here the whole chrome, pill and tab bar, follows it so that both leave together.
    val chromeVisible = toolbarCoordinator?.let { it.frame.collectAsState().value.isVisible }?: true

    // Overlay views (outline, page grid,...) are laid out by the SDK inside the DocumentView, which the chrome
    // covers. Push their content below the chrome while one is shown; the document itself stays put.
    var chromeHeightPx by remember { mutableStateOf(0) }
    LaunchedEffect(overlayViewShown, chromeHeightPx) {
        documentState.setContentViewTopPadding(if (overlayViewShown) chromeHeightPx else 0)
    }

    val chromeColor = MaterialTheme.colorScheme.surfaceContainer
    Box(Modifier.fillMaxSize()) {
        // The document fills the screen and sits behind the chrome, so showing or hiding the chrome never moves it.
        DocumentView(
            documentState = documentState,
            modifier = Modifier.fillMaxSize(),
        )
        AnimatedVisibility(
            visible = chromeVisible,
            enter = slideInVertically { -it } + fadeIn(),
            exit = slideOutVertically { -it } + fadeOut(),
            modifier = Modifier.align(Alignment.TopCenter).background(Color.Transparent),
        ) {
            Column(
                Modifier.fillMaxWidth().background(Color.Transparent).statusBarsPadding().onSizeChanged { chromeHeightPx = it.height },
            ) {
                toolbarCoordinator?.let { coordinator ->
                    // The floating, rounded, elevated main toolbar. NutrientTheme provides the pill's color scheme
                    // to the toolbar items, the title and the overflow popup.
                    NutrientTheme(colorScheme = pillToolbarColors()) {
                        Surface(
                            shape = RoundedCornerShape(PILL_CORNER_RADIUS),
                            shadowElevation = 8.dp,
                            color = Color.Transparent,
                            modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp, vertical = 8.dp).clip(RoundedCornerShape(PILL_CORNER_RADIUS)),
                        ) {
                            NutrientMainToolbar(
                                coordinator = coordinator,
                                // The chrome already offsets the status bar, so the toolbar must not add its own inset.
                                windowInsets = WindowInsets(0, 0, 0, 0),
                                // The chrome animates as a whole, so the toolbar must not animate on its own too.
                                enter = EnterTransition.None,
                                exit = ExitTransition.None,
                            )
                        }
                    }
                }
                documentCoordinator?.let { coordinator ->
                    Row(verticalAlignment = Alignment.CenterVertically) {
                        NutrientTabBar(
                            documentCoordinator = coordinator,
                            modifier = Modifier.weight(1f).padding(top = 5.dp),
                            closeMode = PdfTabBarCloseMode.CLOSE_ONLY_SELECTED_TAB,
                            colors = getTabBarColors(
                                backgroundColor = Color.Transparent,
                                tabColor = MaterialTheme.colorScheme.surface,
                                selectedTabColor = MaterialTheme.colorScheme.primary,
                                selectedTextColor = MaterialTheme.colorScheme.onPrimary,
                            ),
                            dimensions = NutrientTabBarDefaults.dimensions(height = 52.dp, tabMinWidth = 96.dp),
                            tabShape = RoundedCornerShape(PILL_CORNER_RADIUS),
                            tabSpacing = 8.dp,
                            contentPadding = PaddingValues(start = 12.dp, top = 4.dp, end = 4.dp, bottom = 8.dp),
                        )
                        SmallFloatingActionButton({
                            val assetName = MORE_DOCUMENTS[nextDocument % MORE_DOCUMENTS.size]
                            nextDocument++
                            ExtractAssetTask.extract(assetName, assetName, context) { documentFile ->
                                openInNewTab(coordinator, Uri.fromFile(documentFile))
                            }
                        }) {
                            Icon(Icons.Default.Add, contentDescription = stringResource(R.string.documentTabsComposeExampleAddTab))
                        }
                    }
                }
            }
        }
    }
}

/** The pill's color scheme: the app's primary color with white content, for items, title and the overflow popup. */
@Composable
private fun pillToolbarColors(): UiColorScheme {
    val background = MaterialTheme.colorScheme.primary
    return getUiColors().copy(
        mainToolbar = MainToolbarColors(
            backgroundColor = background,
            textColor = Color.White,
            popup = ToolbarPopupColors(backgroundColor = background),
            titleTextColor = Color.White,
        ),
    )
}

/** Adds the document at [uri] to [coordinator] and switches to it, which selects its tab. */
private fun openInNewTab(coordinator: DocumentCoordinator, uri: Uri) {
    val descriptor = DocumentDescriptor.fromUri(uri)
    coordinator.addDocument(descriptor)
    coordinator.setVisibleDocument(descriptor)
}

private val MORE_DOCUMENTS = listOf("Classbook.pdf", "Aviation.pdf", "Annotations.pdf")
private val PILL_CORNER_RADIUS = 28.dp

```

This code sample is an example that illustrates how to use our SDK. Please adapt it to your specific use case.

---

## Related pages

- [Add LTV to Existing Signature](/guides/android/samples/add-ltv-to-existing-signature-kotlin.md)
- [AES Encrypted File](/guides/android/samples/aes-encrypted-file-java.md)
- [AI Assistant (Multiple Documents, Compose)](/guides/android/samples/ai-assistant-multiple-documents-compose-kotlin.md)
- [AI Assistant (Multiple Documents, ViewPager)](/guides/android/samples/ai-assistant-multiple-documents-viewpager-kotlin.md)
- [AI Assistant (Single Document)](/guides/android/samples/ai-assistant-single-document-kotlin.md)
- [Annotation Configuration](/guides/android/samples/annotation-configuration-kotlin.md)
- [Annotation Creation](/guides/android/samples/annotation-creation-kotlin.md)
- [Annotation Flags](/guides/android/samples/annotation-flags-kotlin.md)
- [Annotation Overlay](/guides/android/samples/annotation-overlay-java.md)
- [Annotation Rendering](/guides/android/samples/annotation-rendering-kotlin.md)
- [Annotation Selection Styling](/guides/android/samples/annotation-selection-styling-kotlin.md)
- [Annotation Sidebar](/guides/android/samples/annotation-sidebar-kotlin.md)
- [Annotation Toolbar: Custom Items](/guides/android/samples/annotation-toolbar-custom-items-kotlin.md)
- [Annotation Toolbar: Item Grouping](/guides/android/samples/annotation-toolbar-item-grouping-kotlin.md)
- [Annotation Toolbar: User-Editable Tools](/guides/android/samples/annotation-toolbar-user-editable-tools-kotlin.md)
- [Annotations with Transparency](/guides/android/samples/annotations-with-transparency-kotlin.md)
- [Application Policy](/guides/android/samples/application-policy-kotlin.md)
- [Bookmark Highlighting](/guides/android/samples/bookmark-highlighting-kotlin.md)
- [Compose Image Document](/guides/android/samples/compose-image-document-kotlin.md)
- [Compose Navigation](/guides/android/samples/compose-navigation-kotlin.md)
- [Compose PDF Viewer](/guides/android/samples/compose-pdf-viewer-kotlin.md)
- [Construction Floor Plan](/guides/android/samples/construction-floor-plan-kotlin.md)
- [Custom Activity Form Editing](/guides/android/samples/custom-activity-form-editing-java.md)
- [Custom Annotation Inspector](/guides/android/samples/custom-annotation-inspector-java.md)
- [Custom Data Provider](/guides/android/samples/custom-data-provider-kotlin.md)
- [Custom Download Dialog](/guides/android/samples/custom-download-dialog-java.md)
- [Custom Electronic Signature](/guides/android/samples/custom-electronic-signature-java.md)
- [Custom Form Highlight Color](/guides/android/samples/custom-form-highlight-color-java.md)
- [Custom Layout](/guides/android/samples/custom-layout-kotlin.md)
- [Custom Note Hinter](/guides/android/samples/custom-note-hinter-kotlin.md)
- [Custom Outline Provider](/guides/android/samples/custom-outline-provider-kotlin.md)
- [Custom Page Templates](/guides/android/samples/custom-page-templates-java.md)
- [Custom Search UI (Compose)](/guides/android/samples/custom-search-ui-compose-kotlin.md)
- [Custom Search UI (Views)](/guides/android/samples/custom-search-ui-views-java.md)
- [Custom Settings, Info and Outline UI](/guides/android/samples/custom-settings-info-and-outline-ui-kotlin.md)
- [Custom Sharing Dialog](/guides/android/samples/custom-sharing-dialog-java.md)
- [Custom Sharing Menu](/guides/android/samples/custom-sharing-menu-java.md)
- [Custom Stamp Annotations](/guides/android/samples/custom-stamp-annotations-java.md)
- [Digital Signature (Basic)](/guides/android/samples/digital-signature-basic-kotlin.md)
- [Digital Signature (Manual)](/guides/android/samples/digital-signature-manual-kotlin.md)
- [Digital Signature (Third-Party)](/guides/android/samples/digital-signature-third-party-kotlin.md)
- [Digital Signature (Two-Step)](/guides/android/samples/digital-signature-two-step-kotlin.md)
- [Disabled Annotation Property](/guides/android/samples/disabled-annotation-property-java.md)
- [Document Comparison](/guides/android/samples/document-comparison-kotlin.md)
- [Document Download](/guides/android/samples/document-download-kotlin.md)
- [Document from Canvas](/guides/android/samples/document-from-canvas-kotlin.md)
- [Document Processing](/guides/android/samples/document-processing-kotlin.md)
- [Document Sharing](/guides/android/samples/document-sharing-java.md)
- [Document Switcher](/guides/android/samples/document-switcher-java.md)
- [DocumentView Composable](/guides/android/samples/documentview-composable-kotlin.md)
- [DocumentView in a Dialog](/guides/android/samples/documentview-in-a-dialog-kotlin.md)
- [Download Progress](/guides/android/samples/download-progress-kotlin.md)
- [Dynamic Pages on Scroll](/guides/android/samples/dynamic-pages-on-scroll-kotlin.md)
- [E-Learning](/guides/android/samples/e-learning-kotlin.md)
- [Electronic + Digital Signing](/guides/android/samples/electronic-digital-signing-kotlin.md)
- [External Document](/guides/android/samples/external-document-kotlin.md)
- [File Annotation Creation](/guides/android/samples/file-annotation-creation-kotlin.md)
- [Filterable Thumbnail Grid](/guides/android/samples/filterable-thumbnail-grid-kotlin.md)
- [Form Click Intercept (Compose)](/guides/android/samples/form-click-intercept-compose-kotlin.md)
- [Form Creation](/guides/android/samples/form-creation-kotlin.md)
- [Form Filling](/guides/android/samples/form-filling-kotlin.md)
- [Forms with JavaScript](/guides/android/samples/forms-with-javascript-kotlin.md)
- [Fragment Runtime Configuration](/guides/android/samples/fragment-runtime-configuration-kotlin.md)
- [Generate PDF Report](/guides/android/samples/generate-pdf-report-kotlin.md)
- [Hide and Reveal Areas](/guides/android/samples/hide-and-reveal-areas-kotlin.md)
- [HTML-to-PDF Conversion](/guides/android/samples/html-to-pdf-conversion-kotlin.md)
- [Image Document](/guides/android/samples/image-document-kotlin.md)
- [Inline Multimedia](/guides/android/samples/inline-multimedia-kotlin.md)
- [Instant Document JSON](/guides/android/samples/instant-document-json-kotlin.md)
- [Instant JSON Attachment](/guides/android/samples/instant-json-attachment-kotlin.md)
- [JavaScript Actions](/guides/android/samples/javascript-actions-kotlin.md)
- [JavaScript Calculator](/guides/android/samples/javascript-calculator-kotlin.md)
- [JavaScript Form Filling](/guides/android/samples/javascript-form-filling-kotlin.md)
- [Kiosk Grid](/guides/android/samples/kiosk-grid-kotlin.md)
- [LTV Signature](/guides/android/samples/ltv-signature-kotlin.md)
- [Main Toolbar: Custom Layout & Items](/guides/android/samples/main-toolbar-custom-layout-items-kotlin.md)
- [Main Toolbar: FAB Menu (M3 Expressive)](/guides/android/samples/main-toolbar-fab-menu-m3-expressive-kotlin.md)
- [Main Toolbar: Floating Pill (M3 Expressive)](/guides/android/samples/main-toolbar-floating-pill-m3-expressive-kotlin.md)
- [Measurement Tools](/guides/android/samples/measurement-tools-kotlin.md)
- [Memory Pressure Recovery](/guides/android/samples/memory-pressure-recovery-kotlin.md)
- [Merge Documents](/guides/android/samples/merge-documents-kotlin.md)
- [Multimedia Annotations](/guides/android/samples/multimedia-annotations-kotlin.md)
- [Multiple Documents (Compose Pager)](/guides/android/samples/multiple-documents-compose-pager-kotlin.md)
- [OCR](/guides/android/samples/ocr-kotlin.md)
- [Overlay Views](/guides/android/samples/overlay-views-kotlin.md)
- [Overlay Visibility](/guides/android/samples/overlay-visibility-kotlin.md)
- [Password Protected PDF](/guides/android/samples/password-protected-pdf-kotlin.md)
- [PDF from Image](/guides/android/samples/pdf-from-image-kotlin.md)
- [PdfFragment](/guides/android/samples/pdffragment-kotlin.md)
- [PdfUiFragment](/guides/android/samples/pdfuifragment-kotlin.md)
- [Playground](/guides/android/samples/playground-kotlin.md)
- [Popup Toolbar: Custom Items](/guides/android/samples/popup-toolbar-custom-items-kotlin.md)
- [Programmatic Zoom](/guides/android/samples/programmatic-zoom-kotlin.md)
- [Reader View](/guides/android/samples/reader-view-kotlin.md)
- [Remote URL](/guides/android/samples/remote-url-kotlin.md)
- [Replace and Refresh Documents](/guides/android/samples/replace-and-refresh-documents-kotlin.md)
- [Runtime Configuration](/guides/android/samples/runtime-configuration-kotlin.md)
- [Scientific Paper](/guides/android/samples/scientific-paper-kotlin.md)
- [Screen Reader](/guides/android/samples/screen-reader-java.md)
- [Search Indexing](/guides/android/samples/search-indexing-kotlin.md)
- [Selection Customization](/guides/android/samples/selection-customization-java.md)
- [Signature Parcelize](/guides/android/samples/signature-parcelize-kotlin.md)
- [Signature Storage Database](/guides/android/samples/signature-storage-database-kotlin.md)
- [Sound Extraction](/guides/android/samples/sound-extraction-kotlin.md)
- [Split Screen (Compose)](/guides/android/samples/split-screen-compose-kotlin.md)
- [Split View](/guides/android/samples/split-view-java.md)
- [Tabbed Documents](/guides/android/samples/tabbed-documents-kotlin.md)
- [Tabbed Documents (Persistent)](/guides/android/samples/tabbed-documents-persistent-kotlin.md)
- [Text Field Suggestions](/guides/android/samples/text-field-suggestions-kotlin.md)
- [Thumbnail Bar Modes](/guides/android/samples/thumbnail-bar-modes-kotlin.md)
- [Try Instant](/guides/android/samples/try-instant-kotlin.md)
- [UI View Modes](/guides/android/samples/ui-view-modes-kotlin.md)
- [Vertical Scrollbar](/guides/android/samples/vertical-scrollbar-java.md)
- [Watermarks](/guides/android/samples/watermarks-kotlin.md)
- [XFDF Import/Export](/guides/android/samples/xfdf-import-export-kotlin.md)

