Compose Navigation
Shows how to use DocumentView Composable in NavHost.
/* * Copyright © 2023-2026 PSPDFKit GmbH. All rights reserved. * * The PSPDFKit 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.Contextimport android.content.Intentimport android.graphics.RectFimport android.os.Bundleimport android.widget.Toastimport androidx.activity.compose.setContentimport androidx.activity.enableEdgeToEdgeimport androidx.appcompat.app.AppCompatActivityimport androidx.compose.foundation.backgroundimport androidx.compose.foundation.layout.Boximport androidx.compose.foundation.layout.fillMaxSizeimport androidx.compose.foundation.layout.paddingimport androidx.compose.foundation.layout.statusBarsPaddingimport androidx.compose.material.icons.Iconsimport androidx.compose.material.icons.automirrored.filled.ArrowBackimport androidx.compose.material3.ElevatedButtonimport androidx.compose.material3.ExperimentalMaterial3Apiimport androidx.compose.material3.Iconimport androidx.compose.material3.IconButtonimport androidx.compose.material3.MaterialThemeimport androidx.compose.material3.Scaffoldimport androidx.compose.material3.Textimport androidx.compose.material3.TopAppBarimport androidx.compose.runtime.Composableimport androidx.compose.runtime.rememberimport androidx.compose.ui.Alignmentimport androidx.compose.ui.Modifierimport androidx.core.net.toUriimport androidx.navigation.compose.NavHostimport androidx.navigation.compose.composableimport androidx.navigation.compose.rememberNavControllerimport com.pspdfkit.catalog.Rimport com.pspdfkit.catalog.SdkExampleimport com.pspdfkit.catalog.tasks.ExtractAssetTaskimport com.pspdfkit.configuration.activity.PdfActivityConfigurationimport com.pspdfkit.configuration.activity.UserInterfaceViewModeimport com.pspdfkit.configuration.page.PageFitModeimport com.pspdfkit.configuration.page.PageLayoutModeimport com.pspdfkit.configuration.page.PageScrollDirectionimport com.pspdfkit.configuration.page.PageScrollModeimport com.pspdfkit.forms.TextFormConfigurationimport com.pspdfkit.jetpack.compose.interactors.DefaultListenersimport com.pspdfkit.jetpack.compose.interactors.getDefaultDocumentManagerimport com.pspdfkit.jetpack.compose.interactors.rememberDocumentStateimport com.pspdfkit.jetpack.compose.views.DocumentView
private const val URL_PARAM = "url_param"
/** * This activity shows how DocumentView can be used with Navigation Component. */class NavHostExample(context: Context) : SdkExample(context, R.string.navHostExampleTitle, R.string.navHostExampleDescription) { override fun launchExample(context: Context, configuration: PdfActivityConfiguration.Builder) { // Extract the document from the assets. ExtractAssetTask.extract(WELCOME_DOC, title, context) { url -> context.startActivity( Intent(context, NavHostActivity::class.java).apply { putExtra(URL_PARAM, url.toUri().toString()) } ) } }}
/** * This activity will create a simple navigation flow between two screens, each containing a DocumentView. */class NavHostActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val path = intent.getStringExtra(URL_PARAM) ?: "" enableEdgeToEdge() setContent { MaterialTheme { Scaffold { val navController = rememberNavController() NavHost( navController = navController, startDestination = "ScreenOne", modifier = Modifier.fillMaxSize().padding(it) ) { composable("ScreenOne") { ScreenOne(path) { navController.navigate("ScreenTwo") } } composable("ScreenTwo") { ScreenTwo(path) { navController.popBackStack() } } } } } } }}
/** * ScreenOne contains a DocumentView */@Composablefun ScreenOne(path: String, navigate: () -> Unit) { Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) { val context = androidx.compose.ui.platform.LocalContext.current val pdfActivityConfiguration = remember { PdfActivityConfiguration .Builder(context) .layoutMode(PageLayoutMode.AUTO) .scrollMode(PageScrollMode.CONTINUOUS) .fitMode(PageFitMode.FIT_TO_WIDTH) .pagePadding(8) .scrollDirection(PageScrollDirection.VERTICAL) .setUserInterfaceViewMode(UserInterfaceViewMode.USER_INTERFACE_VIEW_MODE_HIDDEN) .autosaveEnabled(false) .formEditingEnabled(false) .build() }
val documentState = rememberDocumentState(documentUri = path.toUri(), configuration = pdfActivityConfiguration) DocumentView( documentState = documentState, documentManager = getDefaultDocumentManager( documentListener = DefaultListeners.documentListeners( onDocumentLoaded = { i -> i.formProvider .addFormElementToPage<TextFormConfiguration>( "text-field-1", TextFormConfiguration.Builder(0, RectF(30f, 750f, 200f, 720f)) .setText("Hello new Text") .build() ) Toast.makeText(context, "Document loaded!", Toast.LENGTH_SHORT).show() } ) ) ) ElevatedButton(navigate, modifier = Modifier) { Text("Navigate by NavController") } }}
/** * ScreenTwo contains a DocumentView with a slightly different configuration. */@OptIn(ExperimentalMaterial3Api::class)@Composablefun ScreenTwo(path: String, navigate: () -> Unit) { Box(modifier = Modifier.fillMaxSize()) { val context = androidx.compose.ui.platform.LocalContext.current val pdfActivityConfiguration = remember { PdfActivityConfiguration .Builder(context) .layoutMode(PageLayoutMode.AUTO) .scrollMode(PageScrollMode.PER_PAGE) .fitMode(PageFitMode.FIT_TO_WIDTH) .pagePadding(8) .scrollDirection(PageScrollDirection.VERTICAL) .setUserInterfaceViewMode(UserInterfaceViewMode.USER_INTERFACE_VIEW_MODE_HIDDEN) .autosaveEnabled(false) .formEditingEnabled(true) .build() }
val documentState = rememberDocumentState(documentUri = path.toUri(), configuration = pdfActivityConfiguration) DocumentView( documentState = documentState, documentManager = getDefaultDocumentManager( documentListener = DefaultListeners.documentListeners( onDocumentLoaded = { i -> i.formProvider .addFormElementToPage<TextFormConfiguration>( "text-field-editable", TextFormConfiguration.Builder(0, RectF(30f, 750f, 200f, 720f)) .setText("Hello new Text") .build() ) Toast.makeText(context, "Document loaded!", Toast.LENGTH_SHORT).show() } ) ) ) Box(modifier = Modifier.background(MaterialTheme.colorScheme.surface)) { TopAppBar( title = { Text("${documentState.getTitle()}") }, navigationIcon = { IconButton(navigate) { Icon(Icons.AutoMirrored.Default.ArrowBack, contentDescription = "Back") } }, modifier = Modifier.statusBarsPadding() ) } }}This code sample is an example that illustrates how to use our SDK. Please adapt it to your specific use case.